mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-12 19:10:32 +03:00
Refactor uart (#13585)
* serial - refactor serial resource handling - port related resources (tx/rx/inverted,dma) - are stored sequentially, with space in place of ports that are not enabled (RESOURCE_UART_COUNT + RESOURCE_LPUART_COUNT + RESOURCE_SOFTSERIAL_COUNT) - RESOURCE_UART_OFFSET, RESOURCE_LPUART_OFFSET, RESOURCE_SOFTSERIAL_OFFSET - resource entries are pointing into this array (UART, LPUART, SOFTSERIAL) - both pins and DMA - inverter is supproted only for UART + LPUART (makes sense only for UART, to be removed) - softSerialPinConfig is removed, it is no longer necessary - serialResourceIndex(identifier) is used universally to get correct index into resource array - unified handling of resources where possible - serialOwnerTxRx() + serialOwnerIndex() are used for displaying resources correctly to user. - serialType(identifier) implemented - serialOwnerTxRx / serialOwnerIndex are trivial with it - large switch() statemens are greatly simplified * serial - merge code duplicated in all UART implementations - drivers/serial_uart_hw.c contains merged serialUART code. Code did not match exactly. Obvious cases are fixed, more complicated use #ifs - pin inversion unified - uartOpen is refactored a bit * serial - refactor uartDevice - use 'compressed' enum from uartDeviceIdx_e. Only enabled ports are in this enum. - uartDeviceIdx directly indexes uartDevice (no search necessary, no wasted space) - use `serialPortIdentifier_e identifier;` for uartHardware - for DMA remap, define only entries for enabled ports (uartDeviceIdx_e does not exist disabled port) * serial - apply changes to inverter New implementation is trivial * serial - HAL - rxIrq, txIrq replaces by irqn There is only one IRQ for serial * serial - serial_post.h Generated code to normalize target configuration. jinja2 template is used to generate header file. Port handling is unified a lot. SERIAL_<type><n>_USED 0/1 - always defined, value depends on target configuration SERIAL_<type>_MASK - bitmask of used ports or given type. <port>1 is BIT(0) SERIAL_<type>_COUNT - number of enabled ports of given type SERIAL_<type>_MAX - <index of highest used port> + 1, 0 when no port is enabled * targets - remove automatically calculated valued from configs serial_post.h generated it * serial - remove definitions replaced by serial_post.h * serial - change LPUART to UART_LP1 in places LPUART is mostly handled as another UART port, this change reflects it * serial - use ARRAYLEN / ARRAYEND in some places replaces constant that may not match actual array size * serial - adapt softserial to changes * serial - whitespace, comments * softserial - fix serialTimerConfigureTimebase * serial - suspicious code * serial - unittests * serial - cleanup * serial - simpler port names Is this useful ? * serial - no port count for SITL necessary * serial - fix unittests include serial_post.h, some ports are defined, so normalization will work fine * timers - remove obsolete defines from SITL and unittests * serial - cosmetic improvements comments, whitespace, minor refactoring * serial - fix serialInit bug serialPortToDisable was preventing further tests * serial - fix possible NULL pointer dereference * serial - move serialResourceIndex to drivers * serial - refactor pp/od and pulldown/pullup/nopull Centralize serial options handling, decouple it from MCU type Move some code into new drivers/serial_impl.c * serial - make port.identifier valid early in port initialization * serial - fix unittest Code is moved around a bit to make unittests implementation easier * serial - bug - fix off-by-one error uart1/softserial1/lpuart was not working properly because of this * serial - whipespace + formating + style + comments No functional changes * utils - add popcount functions Wrap __builtin_popcount for easier use. Refactor existing code using it. Update code using BITCOUNT macro in dynamic context (BITCOUNT is for compile-time use only) * serial - inverter - simplify code * pinio - prevent array access overflow * serial - refactor SERIAL_BIDIR_* SERIAL_BIDIR_OD / SERIAL_BIDIR_PP SERIAL_PULL_DEFAULT / SERIAL_PULL_NONE / SERIAL_PULL_PD * serial - simplify code minor refactoring - cleaner AVOID_UARTx_FOR_PWM_PPM (unused anyway) - serialFindPortConfiguration* - remove code duplication - use serialType in smartaudio * serial - add port names - const string is assiociated with each compiled-in port (easy to pass around) - findSerialPortByName * cli - improve serialpassthrough - support port options (in current mode argument) - support port names (`serialpassthrough uart1`) - improve error handling; check more parse errors * cli - resources - minor refactor - prevent SERIAL_TX_NONSENSE when parsing resource type - fix possible NULL pointer dereference - store resource tag only after checking all conditions - slighty better error reporting - `resource serial_tx 1` will print resource assignment * serial - remane pulldown to SERIAL_PULL_SMARTAUDIO Make sure nobody uses it by mistake. SERIAL_PULL_SMARTAUDIO_SUPER_DANGEROUS_USE_AT_YOUR_OWN_RISK_THIS_WILL_BREAK_EVERYTHING_AND_KILL_YOUR_PET_FISH would be better choice, but try shorter version first. * smartaudio - minor refactor/improvement - Fix softserial on AT32 - make it easier to handle SA on per-cpu basis * softserial - minor refactoring no functional changes * UART - move AF handling before MCU dependent code * UART - adapt APM32 / APM32F4 code - Modeled after F4 where possible - come code moved from APM32 to APM32F4, possbily not necessary, but it improves similarity with STM32F4 * UART - APM32 - remove per-pin AF * UART - APM32 - bugfix - fix pinswap #if conditions * UART - apply some improvemnts from APM32 to STM32 * UART - add todo for F4 serial speed * UART - fix typo * UART - refactor support for USE_SMARTAUDIO_NOPULLDOWN * UART - typos, comments, minor improvements * UART - move code into enableRxIrq TODO: split into mcu-specific filer (but in sepatate PR) * UART - add UART_TRAIT_xx makes #if test easier and more consistent more traits shall follow * UART - fix variable name unused branch, would trigger compilation error otherwise * UART - use tables instead of switch * UART - smartaudio minor style change + better comments * UART - unify mspPorts iteration * UART - fix spelling * UART - another typo * UART - fix serialResourceIndex offset must be added, not subtracted offset can be negative * UART - fix typo Bad day ... * UART - use const table GCC does optimize it better. Should not cause functional change * UART - use OwnerIndex for inverter - 1 based - only UART has inversion * UART - refactor serial_resource a bit Single table + helper function. New table is easier to read * UART - serial_impl header is necessary * UART - style-only changes typos unify whitespace comment improvement add some const modifiers use cfg in uartConfigureDma minor improvemnt of for loops * UART - remove LPUART inverter LPUART always supports internal inversion, code was incomplete and unused * UART - update jinja template, regenerate files * UART - enable UART module RCC clk before configuring DMA Does not change anything, UART RCCs are enabled unconditionally
This commit is contained in:
parent
a659189bf0
commit
246d04dc57
90 changed files with 2471 additions and 1931 deletions
|
@ -109,9 +109,11 @@ COMMON_SRC = \
|
||||||
drivers/pin_pull_up_down.c \
|
drivers/pin_pull_up_down.c \
|
||||||
drivers/resource.c \
|
drivers/resource.c \
|
||||||
drivers/serial.c \
|
drivers/serial.c \
|
||||||
|
drivers/serial_impl.c \
|
||||||
drivers/serial_pinconfig.c \
|
drivers/serial_pinconfig.c \
|
||||||
drivers/serial_uart.c \
|
drivers/serial_uart.c \
|
||||||
drivers/serial_uart_pinconfig.c \
|
drivers/serial_uart_pinconfig.c \
|
||||||
|
drivers/serial_uart_hw.c \
|
||||||
drivers/sound_beeper.c \
|
drivers/sound_beeper.c \
|
||||||
drivers/stack_check.c \
|
drivers/stack_check.c \
|
||||||
drivers/system.c \
|
drivers/system.c \
|
||||||
|
@ -128,6 +130,7 @@ COMMON_SRC = \
|
||||||
io/beeper.c \
|
io/beeper.c \
|
||||||
io/piniobox.c \
|
io/piniobox.c \
|
||||||
io/serial.c \
|
io/serial.c \
|
||||||
|
io/serial_resource.c \
|
||||||
io/smartaudio_protocol.c \
|
io/smartaudio_protocol.c \
|
||||||
io/statusindicator.c \
|
io/statusindicator.c \
|
||||||
io/tramp_protocol.c \
|
io/tramp_protocol.c \
|
||||||
|
|
|
@ -328,9 +328,10 @@ typedef enum {
|
||||||
} rebootTarget_e;
|
} rebootTarget_e;
|
||||||
|
|
||||||
typedef struct serialPassthroughPort_s {
|
typedef struct serialPassthroughPort_s {
|
||||||
int id;
|
serialPortIdentifier_e id;
|
||||||
uint32_t baud;
|
uint32_t baud;
|
||||||
unsigned mode;
|
portMode_e mode;
|
||||||
|
portOptions_e options;
|
||||||
serialPort_t *port;
|
serialPort_t *port;
|
||||||
} serialPassthroughPort_t;
|
} serialPassthroughPort_t;
|
||||||
|
|
||||||
|
@ -993,7 +994,7 @@ static void cliShowParseError(const char *cmdName)
|
||||||
|
|
||||||
static void cliShowInvalidArgumentCountError(const char *cmdName)
|
static void cliShowInvalidArgumentCountError(const char *cmdName)
|
||||||
{
|
{
|
||||||
cliPrintErrorLinef(cmdName, "INVALID ARGUMENT COUNT", cmdName);
|
cliPrintErrorLinef(cmdName, "INVALID ARGUMENT COUNT");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cliShowArgumentRangeError(const char *cmdName, char *name, int min, int max)
|
static void cliShowArgumentRangeError(const char *cmdName, char *name, int min, int max)
|
||||||
|
@ -1278,7 +1279,7 @@ static void printSerial(dumpFlags_t dumpMask, const serialConfig_t *serialConfig
|
||||||
{
|
{
|
||||||
const char *format = "serial %d %d %ld %ld %ld %ld";
|
const char *format = "serial %d %d %ld %ld %ld %ld";
|
||||||
headingStr = cliPrintSectionHeading(dumpMask, false, headingStr);
|
headingStr = cliPrintSectionHeading(dumpMask, false, headingStr);
|
||||||
for (uint32_t i = 0; i < SERIAL_PORT_COUNT; i++) {
|
for (unsigned i = 0; i < ARRAYLEN(serialConfig->portConfigs); i++) {
|
||||||
if (!serialIsPortAvailable(serialConfig->portConfigs[i].identifier)) {
|
if (!serialIsPortAvailable(serialConfig->portConfigs[i].identifier)) {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -1398,24 +1399,24 @@ static void cliSerial(const char *cmdName, char *cmdline)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_SERIAL_PASSTHROUGH)
|
#if defined(USE_SERIAL_PASSTHROUGH)
|
||||||
static void cbCtrlLine(void *context, uint16_t ctrl)
|
static void cbCtrlLine_reset(void *context, uint16_t ctrl)
|
||||||
{
|
{
|
||||||
#ifdef USE_PINIO
|
|
||||||
int contextValue = (int)(long)context;
|
|
||||||
if (contextValue) {
|
|
||||||
pinioSet(contextValue - 1, !(ctrl & CTRL_LINE_STATE_DTR));
|
|
||||||
} else
|
|
||||||
#endif /* USE_PINIO */
|
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
|
|
||||||
if (!(ctrl & CTRL_LINE_STATE_DTR)) {
|
if (!(ctrl & CTRL_LINE_STATE_DTR)) {
|
||||||
systemReset();
|
systemReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cliParseSerialMode(const char *tok)
|
#ifdef USE_PINIO
|
||||||
|
static void cbCtrlLine_pinIO(void *context, uint16_t ctrl)
|
||||||
{
|
{
|
||||||
int mode = 0;
|
pinioSet((intptr_t)context, !(ctrl & CTRL_LINE_STATE_DTR));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static portMode_e cliParseSerialMode(const char *tok)
|
||||||
|
{
|
||||||
|
portMode_e mode = 0;
|
||||||
|
|
||||||
if (strcasestr(tok, "rx")) {
|
if (strcasestr(tok, "rx")) {
|
||||||
mode |= MODE_RX;
|
mode |= MODE_RX;
|
||||||
|
@ -1427,6 +1428,29 @@ static int cliParseSerialMode(const char *tok)
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static portOptions_e cliParseSerialOptions(const char *tok)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char* tag;
|
||||||
|
portOptions_e val;
|
||||||
|
} map[] = {
|
||||||
|
{"Invert", SERIAL_INVERTED},
|
||||||
|
{"Stop2", SERIAL_STOPBITS_2},
|
||||||
|
{"Even", SERIAL_PARITY_EVEN},
|
||||||
|
{"Bidir", SERIAL_BIDIR},
|
||||||
|
{"Pushpull", SERIAL_BIDIR_PP},
|
||||||
|
{"Saudio", SERIAL_PULL_SMARTAUDIO},
|
||||||
|
{"Check", SERIAL_CHECK_TX},
|
||||||
|
};
|
||||||
|
portOptions_e options = 0;
|
||||||
|
for (unsigned i = 0; i < ARRAYLEN(map); i++) {
|
||||||
|
if (strstr(tok, map[i].tag) != 0) {
|
||||||
|
options |= map[i].val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
||||||
{
|
{
|
||||||
if (isEmpty(cmdline)) {
|
if (isEmpty(cmdline)) {
|
||||||
|
@ -1434,64 +1458,90 @@ static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPassthroughPort_t ports[2] = { {SERIAL_PORT_NONE, 0, 0, NULL}, {cliPort->identifier, 0, 0, cliPort} };
|
serialPassthroughPort_t ports[2] = { {SERIAL_PORT_NONE, 0, 0, 0, NULL}, {cliPort->identifier, 0, 0, 0, cliPort} };
|
||||||
bool enableBaudCb = false;
|
bool enableBaudCb = false;
|
||||||
int port1PinioDtr = 0;
|
|
||||||
bool port1ResetOnDtr = false;
|
|
||||||
#ifdef USE_PWM_OUTPUT
|
|
||||||
bool escSensorPassthrough = false;
|
|
||||||
#endif
|
|
||||||
char *saveptr;
|
|
||||||
char* tok = strtok_r(cmdline, " ", &saveptr);
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
while (tok != NULL) {
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
if (strcasestr(tok, "esc_sensor")) {
|
|
||||||
#ifdef USE_PWM_OUTPUT
|
|
||||||
escSensorPassthrough = true;
|
|
||||||
#endif
|
|
||||||
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_ESC_SENSOR);
|
|
||||||
ports[0].id = portConfig->identifier;
|
|
||||||
} else {
|
|
||||||
ports[0].id = atoi(tok);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ports[0].baud = atoi(tok);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ports[0].mode = cliParseSerialMode(tok);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (strncasecmp(tok, "reset", strlen(tok)) == 0) {
|
|
||||||
port1ResetOnDtr = true;
|
|
||||||
#ifdef USE_PINIO
|
#ifdef USE_PINIO
|
||||||
} else if (strncasecmp(tok, "none", strlen(tok)) == 0) {
|
int port1PinioDtr = -1; // route port2 USB DTR to pinio
|
||||||
port1PinioDtr = 0;
|
#endif
|
||||||
|
bool port1ResetOnDtr = false; // reset board with DTR
|
||||||
|
bool escSensorPassthrough = false;
|
||||||
|
|
||||||
|
char* nexttok = cmdline;
|
||||||
|
char* tok;
|
||||||
|
int index = 0;
|
||||||
|
while ((tok = strsep(&nexttok, " ")) != NULL) {
|
||||||
|
if (*tok == '\0') { // skip adjacent delimiters
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unsigned portN = (index < 4) ? 0 : 1; // port1 / port2
|
||||||
|
switch (index) {
|
||||||
|
case 0: // port1 to open: esc_sensor, portName, port ID port1
|
||||||
|
case 4: // port2 to use (defaults to CLI serial if no more arguments)
|
||||||
|
{
|
||||||
|
serialPortIdentifier_e portId;
|
||||||
|
char* endptr;
|
||||||
|
if (portN == 0 && strcasestr(tok, "esc_sensor") != NULL) {
|
||||||
|
escSensorPassthrough = true;
|
||||||
|
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_ESC_SENSOR);
|
||||||
|
portId = portConfig ? portConfig->identifier : SERIAL_PORT_NONE;
|
||||||
|
} else if (strcasecmp(tok, "cli") == 0) {
|
||||||
|
portId = cliPort->identifier;
|
||||||
|
} else if ((portId = findSerialPortByName(tok, strcasecmp)) >= 0) {
|
||||||
|
// empty
|
||||||
|
} else if ((portId = strtol(tok, &endptr, 10)) >= 0 && *endptr == '\0') {
|
||||||
|
// empty
|
||||||
} else {
|
} else {
|
||||||
port1PinioDtr = atoi(tok);
|
cliPrintLinef("Failed parsing port%d (%s)", portN + 1, tok);
|
||||||
if (port1PinioDtr < 0 || port1PinioDtr > PINIO_COUNT) {
|
return;
|
||||||
cliPrintLinef("Invalid PinIO number %d", port1PinioDtr);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
#endif /* USE_PINIO */
|
|
||||||
}
|
}
|
||||||
break;
|
if (portN == 1) { // port1 is specified, don't use CLI port
|
||||||
case 4:
|
ports[portN].port = NULL;
|
||||||
ports[1].id = atoi(tok);
|
}
|
||||||
ports[1].port = NULL;
|
ports[portN].id = portId;
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
ports[1].baud = atoi(tok);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
ports[1].mode = cliParseSerialMode(tok);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 1: // baudrate
|
||||||
|
case 5: {
|
||||||
|
int baud = atoi(tok);
|
||||||
|
ports[portN].baud = baud;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: // port1 mode (rx/tx/rxtx) + options
|
||||||
|
case 6: // port2 mode + options
|
||||||
|
ports[portN].mode = cliParseSerialMode(tok);
|
||||||
|
ports[portN].options = cliParseSerialOptions(tok);
|
||||||
|
break;
|
||||||
|
case 3: // DTR action
|
||||||
|
if (strcasecmp(tok, "reset") == 0) {
|
||||||
|
port1ResetOnDtr = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcasecmp(tok, "none") == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef USE_PINIO
|
||||||
|
port1PinioDtr = atoi(tok);
|
||||||
|
if (port1PinioDtr < 0 || port1PinioDtr >= PINIO_COUNT) {
|
||||||
|
cliPrintLinef("Invalid PinIO number %d", port1PinioDtr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* USE_PINIO */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cliPrintLinef("Unexpected argument %d (%s)", index + 1, tok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
index++;
|
index++;
|
||||||
tok = strtok_r(NULL, " ", &saveptr);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < ARRAYLEN(ports); i++) {
|
||||||
|
if (findSerialPortIndexByIdentifier(ports[i].id) < 0) {
|
||||||
|
cliPrintLinef("Invalid port%d %d", i + 1, ports[i].id);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
cliPrintLinef("Port%d: %s", i + 1, serialName(ports[i].id, "<invalid>"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Port checks
|
// Port checks
|
||||||
|
@ -1500,74 +1550,70 @@ static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
||||||
return ;
|
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) {
|
if (ports[0].baud == 0 && ports[1].id == SERIAL_PORT_USB_VCP) {
|
||||||
enableBaudCb = true;
|
enableBaudCb = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
serialPort_t **port = &(ports[i].port);
|
serialPassthroughPort_t* cfg = &ports[i];
|
||||||
if (*port != NULL) {
|
if (cfg->port != NULL) { // port already selected, don't touch it (used when port2 defaults to cli)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int portIndex = i + 1;
|
int portIndex = i + 1;
|
||||||
serialPortUsage_t *portUsage = findSerialPortUsageByIdentifier(ports[i].id);
|
serialPortUsage_t *portUsage = findSerialPortUsageByIdentifier(cfg->id);
|
||||||
if (!portUsage || portUsage->serialPort == NULL) {
|
if (!portUsage || portUsage->serialPort == NULL) {
|
||||||
bool isUseDefaultBaud = false;
|
// serial port is not open yet
|
||||||
if (ports[i].baud == 0) {
|
const bool isUseDefaultBaud = cfg->baud == 0;
|
||||||
|
if (isUseDefaultBaud) {
|
||||||
// Set default baud
|
// Set default baud
|
||||||
ports[i].baud = 57600;
|
cfg->baud = 57600;
|
||||||
isUseDefaultBaud = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ports[i].mode) {
|
if (!cfg->mode) {
|
||||||
ports[i].mode = MODE_RXTX;
|
cliPrintLinef("Using RXTX mode as default");
|
||||||
|
cfg->mode = MODE_RXTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
*port = openSerialPort(ports[i].id, FUNCTION_NONE, NULL, NULL,
|
if (cfg->options) {
|
||||||
ports[i].baud, ports[i].mode,
|
cliPrintLinef("Port%d: using options 0x%x",
|
||||||
SERIAL_NOT_INVERTED);
|
portIndex, cfg->options);
|
||||||
if (!*port) {
|
}
|
||||||
|
cfg->port = openSerialPort(cfg->id, FUNCTION_NONE,
|
||||||
|
NULL, NULL, // rxCallback
|
||||||
|
cfg->baud, cfg->mode, cfg->options);
|
||||||
|
if (!cfg->port) {
|
||||||
cliPrintLinef("Port%d could not be opened.", portIndex);
|
cliPrintLinef("Port%d could not be opened.", portIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUseDefaultBaud) {
|
cliPrintf("Port%d opened, %sbaud = %d.\r\n", portIndex, isUseDefaultBaud ? "default ":"", cfg->baud);
|
||||||
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 {
|
} else {
|
||||||
*port = portUsage->serialPort;
|
cfg->port = portUsage->serialPort;
|
||||||
// If the user supplied a mode, override the port's mode, otherwise
|
// If the user supplied a mode, override the port's mode, otherwise
|
||||||
// leave the mode unchanged. serialPassthrough() handles one-way ports.
|
// leave the mode unchanged. serialPassthrough() handles one-way ports.
|
||||||
// Set the baud rate if specified
|
// Set the baud rate if specified
|
||||||
if (ports[i].baud) {
|
if (cfg->baud) {
|
||||||
cliPrintf("Port%d is already open, setting baud = %d.\r\n", portIndex, ports[i].baud);
|
serialSetBaudRate(cfg->port, cfg->baud);
|
||||||
serialSetBaudRate(*port, ports[i].baud);
|
}
|
||||||
} else {
|
cliPrintLinef("Port%d is already open, %sbaud = %d.", portIndex, cfg->baud ? "new " : "", cfg->port->baudRate);
|
||||||
cliPrintf("Port%d is already open, baud = %d.\r\n", portIndex, (*port)->baudRate);
|
|
||||||
|
if (cfg->mode && cfg->port->mode != cfg->mode) {
|
||||||
|
cliPrintLinef("Port%d mode changed from %d to %d.",
|
||||||
|
portIndex, cfg->port->mode, cfg->mode);
|
||||||
|
serialSetMode(cfg->port, cfg->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ports[i].mode && (*port)->mode != ports[i].mode) {
|
if (cfg->options) {
|
||||||
cliPrintf("Port%d mode changed from %d to %d.\r\n",
|
cliPrintLinef("Port%d is open, can't change options from 0x%x to 0x%x",
|
||||||
portIndex, (*port)->mode, ports[i].mode);
|
portIndex, cfg->port->options, cfg->options);
|
||||||
serialSetMode(*port, ports[i].mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this port has a rx callback associated we need to remove it now.
|
// 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!
|
// Otherwise no data will be pushed in the serial port buffer!
|
||||||
if ((*port)->rxCallback) {
|
if (cfg->port->rxCallback) {
|
||||||
(*port)->rxCallback = NULL;
|
cliPrintLinef("Port%d: Callback removed", portIndex);
|
||||||
|
cfg->port->rxCallback = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1580,20 +1626,26 @@ static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
||||||
serialSetBaudRateCb(ports[1].port, serialSetBaudRate, ports[0].port);
|
serialSetBaudRateCb(ports[1].port, serialSetBaudRate, ports[0].port);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *resetMessage = "";
|
const char *resetMessage = "";
|
||||||
if (port1ResetOnDtr && ports[1].id == SERIAL_PORT_USB_VCP) {
|
if (port1ResetOnDtr && ports[1].id == SERIAL_PORT_USB_VCP) {
|
||||||
resetMessage = "or drop DTR ";
|
resetMessage = "or drop DTR ";
|
||||||
}
|
}
|
||||||
|
|
||||||
cliPrintLinef("Forwarding, power cycle %sto exit.", resetMessage);
|
cliPrintLinef("Forwarding, power cycle %sto exit.", resetMessage);
|
||||||
|
|
||||||
if ((ports[1].id == SERIAL_PORT_USB_VCP) && (port1ResetOnDtr
|
if ((ports[1].id == SERIAL_PORT_USB_VCP)) {
|
||||||
|
do {
|
||||||
|
if (port1ResetOnDtr) {
|
||||||
|
serialSetCtrlLineStateCb(ports[1].port, cbCtrlLine_reset, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#ifdef USE_PINIO
|
#ifdef USE_PINIO
|
||||||
|| port1PinioDtr
|
if (port1PinioDtr >= 0) {
|
||||||
|
serialSetCtrlLineStateCb(ports[1].port, cbCtrlLine_pinIO, (void *)(intptr_t)(port1PinioDtr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif /* USE_PINIO */
|
#endif /* USE_PINIO */
|
||||||
)) {
|
} while (0);
|
||||||
// Register control line state callback
|
|
||||||
serialSetCtrlLineStateCb(ports[0].port, cbCtrlLine, (void *)(intptr_t)(port1PinioDtr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Review ESC pass through under refactored motor handling
|
// XXX Review ESC pass through under refactored motor handling
|
||||||
|
@ -1608,7 +1660,7 @@ static void cliSerialPassthrough(const char *cmdName, char *cmdline)
|
||||||
const timerHardware_t *timerHardware = timerGetConfiguredByTag(tag);
|
const timerHardware_t *timerHardware = timerGetConfiguredByTag(tag);
|
||||||
if (timerHardware) {
|
if (timerHardware) {
|
||||||
IO_t io = IOGetByTag(tag);
|
IO_t io = IOGetByTag(tag);
|
||||||
IOInit(io, OWNER_MOTOR, 0);
|
IOInit(io, OWNER_MOTOR, i);
|
||||||
IOConfigGPIO(io, IOCFG_OUT_PP);
|
IOConfigGPIO(io, IOCFG_OUT_PP);
|
||||||
if (timerHardware->output & TIMER_OUTPUT_INVERTED) {
|
if (timerHardware->output & TIMER_OUTPUT_INVERTED) {
|
||||||
IOLo(io);
|
IOLo(io);
|
||||||
|
@ -5022,7 +5074,7 @@ typedef struct {
|
||||||
|
|
||||||
const cliResourceValue_t resourceTable[] = {
|
const cliResourceValue_t resourceTable[] = {
|
||||||
#if defined(USE_BEEPER)
|
#if defined(USE_BEEPER)
|
||||||
DEFS( OWNER_BEEPER, PG_BEEPER_DEV_CONFIG, beeperDevConfig_t, ioTag) ,
|
DEFS( OWNER_BEEPER, PG_BEEPER_DEV_CONFIG, beeperDevConfig_t, ioTag ),
|
||||||
#endif
|
#endif
|
||||||
DEFA( OWNER_MOTOR, PG_MOTOR_CONFIG, motorConfig_t, dev.ioTags[0], MAX_SUPPORTED_MOTORS ),
|
DEFA( OWNER_MOTOR, PG_MOTOR_CONFIG, motorConfig_t, dev.ioTags[0], MAX_SUPPORTED_MOTORS ),
|
||||||
#if defined(USE_SERVOS)
|
#if defined(USE_SERVOS)
|
||||||
|
@ -5041,20 +5093,21 @@ const cliResourceValue_t resourceTable[] = {
|
||||||
#if defined(USE_LED_STRIP)
|
#if defined(USE_LED_STRIP)
|
||||||
DEFS( OWNER_LED_STRIP, PG_LED_STRIP_CONFIG, ledStripConfig_t, ioTag ),
|
DEFS( OWNER_LED_STRIP, PG_LED_STRIP_CONFIG, ledStripConfig_t, ioTag ),
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART
|
#if defined(USE_UART)
|
||||||
DEFA( OWNER_SERIAL_TX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagTx[0], SERIAL_UART_COUNT ),
|
DEFA( OWNER_SERIAL_TX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagTx[RESOURCE_UART_OFFSET], RESOURCE_UART_COUNT ),
|
||||||
DEFA( OWNER_SERIAL_RX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagRx[0], SERIAL_UART_COUNT ),
|
DEFA( OWNER_SERIAL_RX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagRx[RESOURCE_UART_OFFSET], RESOURCE_UART_COUNT ),
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_INVERTER
|
#if defined(USE_INVERTER)
|
||||||
DEFA( OWNER_INVERTER, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagInverter[0], SERIAL_PORT_MAX_INDEX ),
|
DEFA( OWNER_INVERTER, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagInverter[RESOURCE_UART_OFFSET], RESOURCE_UART_COUNT ),
|
||||||
|
// LPUART and SOFTSERIAL don't need external inversion
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_SOFTSERIAL)
|
#if defined(USE_SOFTSERIAL)
|
||||||
DEFA( OWNER_SOFTSERIAL_TX, PG_SOFTSERIAL_PIN_CONFIG, softSerialPinConfig_t, ioTagTx[0], SOFTSERIAL_COUNT ),
|
DEFA( OWNER_SOFTSERIAL_TX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagTx[RESOURCE_SOFTSERIAL_OFFSET], RESOURCE_SOFTSERIAL_COUNT ),
|
||||||
DEFA( OWNER_SOFTSERIAL_RX, PG_SOFTSERIAL_PIN_CONFIG, softSerialPinConfig_t, ioTagRx[0], SOFTSERIAL_COUNT ),
|
DEFA( OWNER_SOFTSERIAL_RX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagRx[RESOURCE_SOFTSERIAL_OFFSET], RESOURCE_SOFTSERIAL_COUNT ),
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LPUART1
|
#if defined(USE_LPUART)
|
||||||
DEFA( OWNER_LPUART_TX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagTx[SERIAL_UART_COUNT], SERIAL_LPUART_COUNT ),
|
DEFA( OWNER_LPUART_TX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagTx[RESOURCE_LPUART_OFFSET], RESOURCE_LPUART_COUNT ),
|
||||||
DEFA( OWNER_LPUART_RX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagRx[SERIAL_UART_COUNT], SERIAL_LPUART_COUNT ),
|
DEFA( OWNER_LPUART_RX, PG_SERIAL_PIN_CONFIG, serialPinConfig_t, ioTagRx[RESOURCE_LPUART_OFFSET], RESOURCE_LPUART_COUNT ),
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_I2C
|
#ifdef USE_I2C
|
||||||
DEFW( OWNER_I2C_SCL, PG_I2C_CONFIG, i2cConfig_t, ioTagScl, I2CDEV_COUNT ),
|
DEFW( OWNER_I2C_SCL, PG_I2C_CONFIG, i2cConfig_t, ioTagScl, I2CDEV_COUNT ),
|
||||||
|
@ -5163,10 +5216,10 @@ const cliResourceValue_t resourceTable[] = {
|
||||||
#undef DEFA
|
#undef DEFA
|
||||||
#undef DEFW
|
#undef DEFW
|
||||||
|
|
||||||
static ioTag_t *getIoTag(const cliResourceValue_t value, uint8_t index)
|
static ioTag_t* getIoTag(const cliResourceValue_t value, uint8_t index)
|
||||||
{
|
{
|
||||||
const pgRegistry_t* rec = pgFind(value.pgn);
|
const pgRegistry_t* rec = pgFind(value.pgn);
|
||||||
return CONST_CAST(ioTag_t *, rec->address + value.stride * index + value.offset);
|
return (ioTag_t *)(rec->address + value.stride * index + value.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printResource(dumpFlags_t dumpMask, const char *headingStr)
|
static void printResource(dumpFlags_t dumpMask, const char *headingStr)
|
||||||
|
@ -5321,6 +5374,7 @@ typedef struct dmaoptEntry_s {
|
||||||
// DEFS : Single entry
|
// DEFS : Single entry
|
||||||
// DEFA : Array of uint8_t (stride = 1)
|
// DEFA : Array of uint8_t (stride = 1)
|
||||||
// DEFW : Wider stride case; array of structs.
|
// DEFW : Wider stride case; array of structs.
|
||||||
|
// DEFW_OFS: array of structs, starting at offset ofs
|
||||||
|
|
||||||
#define DEFS(device, peripheral, pgn, type, member) \
|
#define DEFS(device, peripheral, pgn, type, member) \
|
||||||
{ device, peripheral, pgn, 0, offsetof(type, member), 0, MASK_IGNORED }
|
{ device, peripheral, pgn, 0, offsetof(type, member), 0, MASK_IGNORED }
|
||||||
|
@ -5329,7 +5383,10 @@ typedef struct dmaoptEntry_s {
|
||||||
{ device, peripheral, pgn, sizeof(uint8_t), offsetof(type, member), max, mask }
|
{ device, peripheral, pgn, sizeof(uint8_t), offsetof(type, member), max, mask }
|
||||||
|
|
||||||
#define DEFW(device, peripheral, pgn, type, member, max, mask) \
|
#define DEFW(device, peripheral, pgn, type, member, max, mask) \
|
||||||
{ device, peripheral, pgn, sizeof(type), offsetof(type, member), max, mask }
|
DEFW_OFS(device, peripheral, pgn, type, member, 0, max, mask)
|
||||||
|
|
||||||
|
#define DEFW_OFS(device, peripheral, pgn, type, member, ofs, max, mask) \
|
||||||
|
{ device, peripheral, pgn, sizeof(type), offsetof(type, member) + (ofs) * sizeof(type), max, mask }
|
||||||
|
|
||||||
dmaoptEntry_t dmaoptEntryTable[] = {
|
dmaoptEntry_t dmaoptEntryTable[] = {
|
||||||
DEFW("SPI_SDO", DMA_PERIPH_SPI_SDO, PG_SPI_PIN_CONFIG, spiPinConfig_t, txDmaopt, SPIDEV_COUNT, MASK_IGNORED),
|
DEFW("SPI_SDO", DMA_PERIPH_SPI_SDO, PG_SPI_PIN_CONFIG, spiPinConfig_t, txDmaopt, SPIDEV_COUNT, MASK_IGNORED),
|
||||||
|
@ -5339,8 +5396,14 @@ dmaoptEntry_t dmaoptEntryTable[] = {
|
||||||
DEFW("SPI_RX", DMA_PERIPH_SPI_SDI, PG_SPI_PIN_CONFIG, spiPinConfig_t, rxDmaopt, SPIDEV_COUNT, MASK_IGNORED),
|
DEFW("SPI_RX", DMA_PERIPH_SPI_SDI, PG_SPI_PIN_CONFIG, spiPinConfig_t, rxDmaopt, SPIDEV_COUNT, MASK_IGNORED),
|
||||||
DEFA("ADC", DMA_PERIPH_ADC, PG_ADC_CONFIG, adcConfig_t, dmaopt, ADCDEV_COUNT, MASK_IGNORED),
|
DEFA("ADC", DMA_PERIPH_ADC, PG_ADC_CONFIG, adcConfig_t, dmaopt, ADCDEV_COUNT, MASK_IGNORED),
|
||||||
DEFS("SDIO", DMA_PERIPH_SDIO, PG_SDIO_CONFIG, sdioConfig_t, dmaopt),
|
DEFS("SDIO", DMA_PERIPH_SDIO, PG_SDIO_CONFIG, sdioConfig_t, dmaopt),
|
||||||
DEFW("UART_TX", DMA_PERIPH_UART_TX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, txDmaopt, UARTDEV_CONFIG_MAX, MASK_IGNORED),
|
#ifdef USE_UART
|
||||||
DEFW("UART_RX", DMA_PERIPH_UART_RX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, rxDmaopt, UARTDEV_CONFIG_MAX, MASK_IGNORED),
|
DEFW_OFS("UART_TX", DMA_PERIPH_UART_TX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, txDmaopt, RESOURCE_UART_OFFSET, RESOURCE_UART_COUNT, MASK_IGNORED),
|
||||||
|
DEFW_OFS("UART_RX", DMA_PERIPH_UART_RX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, rxDmaopt, RESOURCE_UART_OFFSET, RESOURCE_UART_COUNT, MASK_IGNORED),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_LPUART
|
||||||
|
DEFW_OFS("LPUART_TX", DMA_PERIPH_UART_TX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, txDmaopt, RESOURCE_LPUART_OFFSET, RESOURCE_LPUART_COUNT, MASK_IGNORED),
|
||||||
|
DEFW_OFS("LPUART_RX", DMA_PERIPH_UART_RX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, rxDmaopt, RESOURCE_LPUART_OFFSET, RESOURCE_LPUART_COUNT, MASK_IGNORED),
|
||||||
|
#endif
|
||||||
#if defined(STM32H7) || defined(STM32G4)
|
#if defined(STM32H7) || defined(STM32G4)
|
||||||
DEFW("TIMUP", DMA_PERIPH_TIMUP, PG_TIMER_UP_CONFIG, timerUpConfig_t, dmaopt, HARDWARE_TIMER_DEFINITION_COUNT, TIMUP_TIMERS),
|
DEFW("TIMUP", DMA_PERIPH_TIMUP, PG_TIMER_UP_CONFIG, timerUpConfig_t, dmaopt, HARDWARE_TIMER_DEFINITION_COUNT, TIMUP_TIMERS),
|
||||||
#endif
|
#endif
|
||||||
|
@ -6071,7 +6134,7 @@ static void cliResource(const char *cmdName, char *cmdline)
|
||||||
}
|
}
|
||||||
|
|
||||||
pch = strtok_r(NULL, " ", &saveptr);
|
pch = strtok_r(NULL, " ", &saveptr);
|
||||||
int index = atoi(pch);
|
int index = pch ? atoi(pch) : 0;
|
||||||
|
|
||||||
if (resourceTable[resourceIndex].maxIndex > 0 || index > 0) {
|
if (resourceTable[resourceIndex].maxIndex > 0 || index > 0) {
|
||||||
if (index <= 0 || index > RESOURCE_VALUE_MAX_INDEX(resourceTable[resourceIndex].maxIndex)) {
|
if (index <= 0 || index > RESOURCE_VALUE_MAX_INDEX(resourceTable[resourceIndex].maxIndex)) {
|
||||||
|
@ -6083,11 +6146,13 @@ static void cliResource(const char *cmdName, char *cmdline)
|
||||||
pch = strtok_r(NULL, " ", &saveptr);
|
pch = strtok_r(NULL, " ", &saveptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ioTag_t *tag = getIoTag(resourceTable[resourceIndex], index);
|
ioTag_t *resourceTag = getIoTag(resourceTable[resourceIndex], index);
|
||||||
|
|
||||||
if (strlen(pch) > 0) {
|
if (pch && strlen(pch) > 0) {
|
||||||
if (strToPin(pch, tag)) {
|
ioTag_t tag;
|
||||||
if (*tag == IO_TAG_NONE) {
|
if (strToPin(pch, &tag)) {
|
||||||
|
if (!tag) {
|
||||||
|
*resourceTag = tag;
|
||||||
#ifdef MINIMAL_CLI
|
#ifdef MINIMAL_CLI
|
||||||
cliPrintLine("Freed");
|
cliPrintLine("Freed");
|
||||||
#else
|
#else
|
||||||
|
@ -6095,9 +6160,10 @@ static void cliResource(const char *cmdName, char *cmdline)
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
ioRec_t *rec = IO_Rec(IOGetByTag(*tag));
|
ioRec_t *rec = IO_Rec(IOGetByTag(tag));
|
||||||
if (rec) {
|
if (rec) {
|
||||||
resourceCheck(resourceIndex, index, *tag);
|
*resourceTag = tag;
|
||||||
|
resourceCheck(resourceIndex, index, tag);
|
||||||
#ifdef MINIMAL_CLI
|
#ifdef MINIMAL_CLI
|
||||||
cliPrintLinef(" %c%02d set", IO_GPIOPortIdx(rec) + 'A', IO_GPIOPinIdx(rec));
|
cliPrintLinef(" %c%02d set", IO_GPIOPortIdx(rec) + 'A', IO_GPIOPinIdx(rec));
|
||||||
#else
|
#else
|
||||||
|
@ -6106,12 +6172,18 @@ static void cliResource(const char *cmdName, char *cmdline)
|
||||||
} else {
|
} else {
|
||||||
cliShowParseError(cmdName);
|
cliShowParseError(cmdName);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cliPrintErrorLinef(cmdName, "Failed to parse '%s' as pin", pch);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ioTag_t tag = *resourceTag;
|
||||||
|
char ioName[5];
|
||||||
|
if (tag) {
|
||||||
|
tfp_sprintf(ioName, "%c%02d", IO_GPIOPortIdxByTag(tag) + 'A', IO_GPIOPinIdxByTag(tag));
|
||||||
|
}
|
||||||
|
cliPrintLinef("# resource %s %d %s", ownerNames[resourceTable[resourceIndex].owner], RESOURCE_INDEX(index), tag ? ioName : "NONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
cliShowParseError(cmdName);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
#include "printf_serial.h"
|
#include "printf_serial.h"
|
||||||
|
|
||||||
#ifdef SERIAL_PORT_COUNT
|
#if SERIAL_PORT_COUNT > 0
|
||||||
|
|
||||||
static serialPort_t *printfSerialPort;
|
static serialPort_t *printfSerialPort;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,11 @@ http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
||||||
#define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
|
#define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
|
||||||
#define BX_(x) ((x) - (((x)>>1)&0x77777777) - (((x)>>2)&0x33333333) - (((x)>>3)&0x11111111))
|
#define BX_(x) ((x) - (((x)>>1)&0x77777777) - (((x)>>2)&0x33333333) - (((x)>>3)&0x11111111))
|
||||||
|
|
||||||
|
static inline int popcount(unsigned x) { return __builtin_popcount(x); }
|
||||||
|
static inline int popcount32(uint32_t x) { return __builtin_popcount(x); }
|
||||||
|
static inline int popcount64(uint64_t x) { return __builtin_popcountll(x); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* https://groups.google.com/forum/?hl=en#!msg/comp.lang.c/attFnqwhvGk/sGBKXvIkY3AJ
|
* https://groups.google.com/forum/?hl=en#!msg/comp.lang.c/attFnqwhvGk/sGBKXvIkY3AJ
|
||||||
|
|
|
@ -416,11 +416,16 @@ static void validateAndFixConfig(void)
|
||||||
if (systemConfig()->configurationState == CONFIGURATION_STATE_UNCONFIGURED) {
|
if (systemConfig()->configurationState == CONFIGURATION_STATE_UNCONFIGURED) {
|
||||||
// enable some compiled-in features by default
|
// enable some compiled-in features by default
|
||||||
uint32_t autoFeatures =
|
uint32_t autoFeatures =
|
||||||
FEATURE_OSD | FEATURE_LED_STRIP
|
FEATURE_OSD | FEATURE_LED_STRIP;
|
||||||
#if defined(SOFTSERIAL1_RX_PIN) || defined(SOFTSERIAL2_RX_PIN) || defined(SOFTSERIAL1_TX_PIN) || defined(SOFTSERIAL2_TX_PIN)
|
#if defined(USE_SOFTSERIAL)
|
||||||
| FEATURE_SOFTSERIAL
|
// enable softserial if at least one pin is configured
|
||||||
|
for (unsigned i = RESOURCE_SOFTSERIAL_OFFSET; i < RESOURCE_SOFTSERIAL_OFFSET + RESOURCE_SOFTSERIAL_COUNT; i++) {
|
||||||
|
if (serialPinConfig()->ioTagTx[i] || serialPinConfig()->ioTagRx[i]) {
|
||||||
|
autoFeatures |= FEATURE_SOFTSERIAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
;
|
|
||||||
featureEnableImmediate(autoFeatures & featuresSupportedByBuild);
|
featureEnableImmediate(autoFeatures & featuresSupportedByBuild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,12 +535,11 @@ static void validateAndFixConfig(void)
|
||||||
// Find the first serial port on which MSP Displayport is enabled
|
// Find the first serial port on which MSP Displayport is enabled
|
||||||
displayPortMspSetSerial(SERIAL_PORT_NONE);
|
displayPortMspSetSerial(SERIAL_PORT_NONE);
|
||||||
|
|
||||||
for (uint8_t serialPort = 0; serialPort < SERIAL_PORT_COUNT; serialPort++) {
|
for (const serialPortConfig_t *portConfig = serialConfig()->portConfigs;
|
||||||
const serialPortConfig_t *portConfig = &serialConfig()->portConfigs[serialPort];
|
portConfig < ARRAYEND(serialConfig()->portConfigs);
|
||||||
|
portConfig++) {
|
||||||
if (portConfig &&
|
if ((portConfig->identifier != SERIAL_PORT_USB_VCP)
|
||||||
(portConfig->identifier != SERIAL_PORT_USB_VCP) &&
|
&& ((portConfig->functionMask & (FUNCTION_VTX_MSP | FUNCTION_MSP)) == (FUNCTION_VTX_MSP | FUNCTION_MSP))) {
|
||||||
((portConfig->functionMask & (FUNCTION_VTX_MSP | FUNCTION_MSP)) == (FUNCTION_VTX_MSP | FUNCTION_MSP))) {
|
|
||||||
displayPortMspSetSerial(portConfig->identifier);
|
displayPortMspSetSerial(portConfig->identifier);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ typedef enum {
|
||||||
DMA_PERIPH_SPI_SDI,
|
DMA_PERIPH_SPI_SDI,
|
||||||
DMA_PERIPH_ADC,
|
DMA_PERIPH_ADC,
|
||||||
DMA_PERIPH_SDIO,
|
DMA_PERIPH_SDIO,
|
||||||
DMA_PERIPH_UART_TX,
|
DMA_PERIPH_UART_TX, // LPUART is handled as UART
|
||||||
DMA_PERIPH_UART_RX,
|
DMA_PERIPH_UART_RX,
|
||||||
DMA_PERIPH_TIMUP,
|
DMA_PERIPH_TIMUP,
|
||||||
} dmaPeripheral_e;
|
} dmaPeripheral_e;
|
||||||
|
|
|
@ -25,33 +25,40 @@
|
||||||
|
|
||||||
#ifdef USE_INVERTER
|
#ifdef USE_INVERTER
|
||||||
|
|
||||||
#include "io/serial.h" // For SERIAL_PORT_IDENTIFIER_TO_INDEX
|
#include "io/serial.h"
|
||||||
#include "drivers/io.h"
|
#include "drivers/io.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
#include "drivers/serial_impl.h"
|
||||||
|
|
||||||
|
|
||||||
#include "inverter.h"
|
#include "inverter.h"
|
||||||
|
|
||||||
static const serialPinConfig_t *pSerialPinConfig;
|
static const serialPinConfig_t *pSerialPinConfig;
|
||||||
|
|
||||||
static void inverterSet(int identifier, bool on)
|
static IO_t findInverterPin(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
IO_t pin = IOGetByTag(pSerialPinConfig->ioTagInverter[SERIAL_PORT_IDENTIFIER_TO_INDEX(identifier)]);
|
const int resourceIndex = serialResourceIndex(identifier);
|
||||||
|
if (resourceIndex >= 0 && resourceIndex < (int)ARRAYLEN(pSerialPinConfig->ioTagInverter)) {
|
||||||
if (pin) {
|
return IOGetByTag(pSerialPinConfig->ioTagInverter[resourceIndex]);
|
||||||
IOWrite(pin, on);
|
} else {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initInverter(int identifier)
|
static void inverterSet(IO_t pin, bool on)
|
||||||
{
|
{
|
||||||
int uartIndex = SERIAL_PORT_IDENTIFIER_TO_INDEX(identifier);
|
IOWrite(pin, on);
|
||||||
IO_t pin = IOGetByTag(pSerialPinConfig->ioTagInverter[uartIndex]);
|
}
|
||||||
|
|
||||||
|
static void initInverter(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
IO_t pin = findInverterPin(identifier);
|
||||||
if (pin) {
|
if (pin) {
|
||||||
IOInit(pin, OWNER_INVERTER, RESOURCE_INDEX(uartIndex));
|
const int ownerIndex = serialOwnerIndex(identifier);
|
||||||
|
// only UART supports inverter, so OWNER_INVERTER+ownerIndex does work
|
||||||
|
IOInit(pin, OWNER_INVERTER, ownerIndex);
|
||||||
IOConfigGPIO(pin, IOCFG_OUT_PP);
|
IOConfigGPIO(pin, IOCFG_OUT_PP);
|
||||||
|
inverterSet(pin, false);
|
||||||
inverterSet(identifier, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,73 +66,18 @@ void initInverters(const serialPinConfig_t *serialPinConfigToUse)
|
||||||
{
|
{
|
||||||
pSerialPinConfig = serialPinConfigToUse;
|
pSerialPinConfig = serialPinConfigToUse;
|
||||||
|
|
||||||
#ifdef USE_UART1
|
for (unsigned i = 0; i < ARRAYLEN(serialPortIdentifiers); i++) {
|
||||||
initInverter(SERIAL_PORT_USART1);
|
// it is safe to pass port without inverter
|
||||||
#endif
|
initInverter(serialPortIdentifiers[i]);
|
||||||
|
}
|
||||||
#ifdef USE_UART2
|
|
||||||
initInverter(SERIAL_PORT_USART2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART3
|
|
||||||
initInverter(SERIAL_PORT_USART3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART4
|
|
||||||
initInverter(SERIAL_PORT_UART4);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART5
|
|
||||||
initInverter(SERIAL_PORT_UART5);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART6
|
|
||||||
initInverter(SERIAL_PORT_USART6);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableInverter(USART_TypeDef *USARTx, bool on)
|
void enableInverter(serialPortIdentifier_e identifier, bool on)
|
||||||
{
|
{
|
||||||
int identifier = SERIAL_PORT_NONE;
|
const IO_t pin = findInverterPin(identifier);
|
||||||
|
if (pin) {
|
||||||
#ifdef USE_UART1
|
inverterSet(pin, on);
|
||||||
if (USARTx == USART1) {
|
|
||||||
identifier = SERIAL_PORT_USART1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART2
|
|
||||||
if (USARTx == USART2) {
|
|
||||||
identifier = SERIAL_PORT_USART2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART3
|
|
||||||
if (USARTx == USART3) {
|
|
||||||
identifier = SERIAL_PORT_USART3;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART4
|
|
||||||
if (USARTx == UART4) {
|
|
||||||
identifier = SERIAL_PORT_UART4;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART5
|
|
||||||
if (USARTx == UART5) {
|
|
||||||
identifier = SERIAL_PORT_UART5;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART6
|
|
||||||
if (USARTx == USART6) {
|
|
||||||
identifier = SERIAL_PORT_USART6;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (identifier != SERIAL_PORT_NONE) {
|
|
||||||
inverterSet(identifier, on);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_INVERTER
|
#endif // USE_INVERTER
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
void initInverters(const serialPinConfig_t *serialPinConfigToUse);
|
void initInverters(const serialPinConfig_t *serialPinConfigToUse);
|
||||||
|
void enableInverter(serialPortIdentifier_e portId, bool on);
|
||||||
void enableInverter(USART_TypeDef *USARTx, bool on);
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ IO_t IOGetByTag(ioTag_t tag)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// count bits before this pin on single port
|
// count bits before this pin on single port
|
||||||
int offset = __builtin_popcount(((1 << pinIdx) - 1) & ioDefUsedMask[portIdx]);
|
int offset = popcount(((1 << pinIdx) - 1) & ioDefUsedMask[portIdx]);
|
||||||
// and add port offset
|
// and add port offset
|
||||||
offset += ioDefUsedOffset[portIdx];
|
offset += ioDefUsedOffset[portIdx];
|
||||||
return ioRecs + offset;
|
return ioRecs + offset;
|
||||||
|
|
|
@ -38,7 +38,10 @@
|
||||||
|
|
||||||
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
|
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
|
||||||
|
|
||||||
//speed is packed inside modebits 5 and 2,
|
// speed is packed between modebits 4 and 1,
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// 0 <pupd-1> <pupd-0> <mode-4> <speed-1> <speed-0> <mode-1> <mode-0>
|
||||||
|
// mode-4 is equivalent to STM32F4 otype (pushpull/od)
|
||||||
#define IO_CONFIG(mode, speed, pupd) ((mode) | ((speed) << 2) | ((pupd) << 5))
|
#define IO_CONFIG(mode, speed, pupd) ((mode) | ((speed) << 2) | ((pupd) << 5))
|
||||||
|
|
||||||
#define IOCFG_OUT_PP IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_LOW, GPIO_NOPULL)
|
#define IOCFG_OUT_PP IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_LOW, GPIO_NOPULL)
|
||||||
|
@ -86,7 +89,7 @@
|
||||||
#define IOCFG_IPD IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_DOWN)
|
#define IOCFG_IPD IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_DOWN)
|
||||||
#define IOCFG_IPU IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_UP)
|
#define IOCFG_IPU IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_UP)
|
||||||
#define IOCFG_IN_FLOATING IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_NONE)
|
#define IOCFG_IN_FLOATING IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_NONE)
|
||||||
#define IOCFG_IPU_25 IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE , 0, GPIO_PULL_UP)
|
#define IOCFG_IPU_25 IO_CONFIG(GPIO_MODE_INPUT , GPIO_DRIVE_STRENGTH_MODERATE, 0, GPIO_PULL_UP)
|
||||||
|
|
||||||
#elif defined(APM32F4)
|
#elif defined(APM32F4)
|
||||||
|
|
||||||
|
|
|
@ -77,19 +77,23 @@
|
||||||
#define NVIC_PRIO_SPI_DMA NVIC_BUILD_PRIORITY(0, 0)
|
#define NVIC_PRIO_SPI_DMA NVIC_BUILD_PRIORITY(0, 0)
|
||||||
#define NVIC_PRIO_SDIO_DMA NVIC_BUILD_PRIORITY(0, 0)
|
#define NVIC_PRIO_SDIO_DMA NVIC_BUILD_PRIORITY(0, 0)
|
||||||
|
|
||||||
#ifdef USE_HAL_DRIVER
|
|
||||||
// utility macros to join/split priority
|
// utility macros to join/split priority
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
|
||||||
#define NVIC_PRIORITY_GROUPING NVIC_PRIORITYGROUP_2
|
#define NVIC_PRIORITY_GROUPING NVIC_PRIORITYGROUP_2
|
||||||
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING)))))<<4)&0xf0)
|
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING)))))<<4)&0xf0)
|
||||||
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
||||||
#define NVIC_PRIORITY_SUB(prio) (((prio)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
#define NVIC_PRIORITY_SUB(prio) (((prio)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
||||||
|
|
||||||
#elif defined(USE_ATBSP_DRIVER)
|
#elif defined(USE_ATBSP_DRIVER)
|
||||||
|
|
||||||
#define NVIC_PRIORITY_GROUPING NVIC_PRIORITY_GROUP_2
|
#define NVIC_PRIORITY_GROUPING NVIC_PRIORITY_GROUP_2
|
||||||
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING)))))<<4)&0xf0)
|
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING)))))<<4)&0xf0)
|
||||||
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING))))>>4)
|
||||||
#define NVIC_PRIORITY_SUB(prio) (((prio)&((0x0f>>(7-(NVIC_PRIORITY_GROUPING)))<<4))>>4)
|
#define NVIC_PRIORITY_SUB(prio) (((prio)&((0x0f>>(7-(NVIC_PRIORITY_GROUPING)))<<4))>>4)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// utility macros to join/split priority
|
|
||||||
#define NVIC_PRIORITY_GROUPING NVIC_PriorityGroup_2
|
#define NVIC_PRIORITY_GROUPING NVIC_PriorityGroup_2
|
||||||
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0)
|
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0)
|
||||||
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING>>8))))>>4)
|
#define NVIC_PRIORITY_BASE(prio) (((prio)>>(4-(7-(NVIC_PRIORITY_GROUPING>>8))))>>4)
|
||||||
|
|
|
@ -60,8 +60,7 @@ void pinioInit(const pinioConfig_t *pinioConfig)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pinioConfig->config[i] & PINIO_CONFIG_OUT_INVERTED)
|
if (pinioConfig->config[i] & PINIO_CONFIG_OUT_INVERTED) {
|
||||||
{
|
|
||||||
pinioRuntime[i].inverted = true;
|
pinioRuntime[i].inverted = true;
|
||||||
IOHi(io);
|
IOHi(io);
|
||||||
pinioRuntime[i].state = true;
|
pinioRuntime[i].state = true;
|
||||||
|
@ -76,7 +75,10 @@ void pinioInit(const pinioConfig_t *pinioConfig)
|
||||||
|
|
||||||
void pinioSet(int index, bool on)
|
void pinioSet(int index, bool on)
|
||||||
{
|
{
|
||||||
bool newState = on ^ pinioRuntime[index].inverted;
|
if (index < 0 || index >= PINIO_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bool newState = on ^ pinioRuntime[index].inverted;
|
||||||
if (newState != pinioRuntime[index].state) {
|
if (newState != pinioRuntime[index].state) {
|
||||||
IOWrite(pinioRuntime[index].io, newState);
|
IOWrite(pinioRuntime[index].io, newState);
|
||||||
pinioRuntime[index].state = newState;
|
pinioRuntime[index].state = newState;
|
||||||
|
|
|
@ -34,8 +34,8 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
|
||||||
"ADC_CURR",
|
"ADC_CURR",
|
||||||
"ADC_EXT",
|
"ADC_EXT",
|
||||||
"ADC_RSSI",
|
"ADC_RSSI",
|
||||||
"SERIAL_TX",
|
[OWNER_SERIAL_TX] = "SERIAL_TX",
|
||||||
"SERIAL_RX",
|
[OWNER_SERIAL_RX] = "SERIAL_RX",
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
"TIMER",
|
"TIMER",
|
||||||
"SONAR_TRIGGER",
|
"SONAR_TRIGGER",
|
||||||
|
@ -111,9 +111,9 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
|
||||||
"SWD",
|
"SWD",
|
||||||
"RX_SPI_EXPRESSLRS_RESET",
|
"RX_SPI_EXPRESSLRS_RESET",
|
||||||
"RX_SPI_EXPRESSLRS_BUSY",
|
"RX_SPI_EXPRESSLRS_BUSY",
|
||||||
"SOFTSERIAL_TX",
|
[OWNER_SOFTSERIAL_TX] = "SOFTSERIAL_TX",
|
||||||
"SOFTSERIAL_RX",
|
[OWNER_SOFTSERIAL_RX] = "SOFTSERIAL_RX",
|
||||||
"LPUART_TX",
|
[OWNER_LPUART_TX] = "LPUART_TX",
|
||||||
"LPUART_RX",
|
[OWNER_LPUART_RX] = "LPUART_RX",
|
||||||
"GYRO_CLKIN",
|
"GYRO_CLKIN",
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ typedef enum {
|
||||||
OWNER_ADC_CURR,
|
OWNER_ADC_CURR,
|
||||||
OWNER_ADC_EXT,
|
OWNER_ADC_EXT,
|
||||||
OWNER_ADC_RSSI,
|
OWNER_ADC_RSSI,
|
||||||
OWNER_SERIAL_TX,
|
OWNER_SERIAL_TX, // TX must be just before RX
|
||||||
OWNER_SERIAL_RX,
|
OWNER_SERIAL_RX,
|
||||||
OWNER_PINDEBUG,
|
OWNER_PINDEBUG,
|
||||||
OWNER_TIMER,
|
OWNER_TIMER,
|
||||||
|
@ -109,9 +109,9 @@ typedef enum {
|
||||||
OWNER_SWD,
|
OWNER_SWD,
|
||||||
OWNER_RX_SPI_EXPRESSLRS_RESET,
|
OWNER_RX_SPI_EXPRESSLRS_RESET,
|
||||||
OWNER_RX_SPI_EXPRESSLRS_BUSY,
|
OWNER_RX_SPI_EXPRESSLRS_BUSY,
|
||||||
OWNER_SOFTSERIAL_TX,
|
OWNER_SOFTSERIAL_TX, // TX must be just before RX
|
||||||
OWNER_SOFTSERIAL_RX,
|
OWNER_SOFTSERIAL_RX,
|
||||||
OWNER_LPUART_TX,
|
OWNER_LPUART_TX, // TX must be just before RX
|
||||||
OWNER_LPUART_RX,
|
OWNER_LPUART_RX,
|
||||||
OWNER_GYRO_CLKIN,
|
OWNER_GYRO_CLKIN,
|
||||||
OWNER_TOTAL_COUNT
|
OWNER_TOTAL_COUNT
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
void serialPrint(serialPort_t *instance, const char *str)
|
void serialPrint(serialPort_t *instance, const char *str)
|
||||||
|
@ -130,3 +131,4 @@ void serialWriteBufShim(void *instance, const uint8_t *data, int count)
|
||||||
{
|
{
|
||||||
serialWriteBuf((serialPort_t *)instance, data, count);
|
serialWriteBuf((serialPort_t *)instance, data, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,7 @@
|
||||||
#include "drivers/io.h"
|
#include "drivers/io.h"
|
||||||
#include "drivers/io_types.h"
|
#include "drivers/io_types.h"
|
||||||
#include "drivers/resource.h"
|
#include "drivers/resource.h"
|
||||||
// TODO(hertz@): uncomment and use UARTDevice_e::MAX_UARTDEV
|
#include "drivers/serial_resource.h"
|
||||||
// #include "drivers/serial_uart.h"
|
|
||||||
|
|
||||||
#include "pg/pg.h"
|
#include "pg/pg.h"
|
||||||
|
|
||||||
|
@ -45,18 +44,27 @@ typedef enum {
|
||||||
SERIAL_BIDIR = 1 << 3,
|
SERIAL_BIDIR = 1 << 3,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note on SERIAL_BIDIR_PP
|
* Note on SERIAL_BIDIR_PP *on some MCU families*
|
||||||
* With SERIAL_BIDIR_PP, the very first start bit of back-to-back bytes
|
* With SERIAL_BIDIR_PP, the very first start bit of back-to-back bytes
|
||||||
* is lost and the first data byte will be lost by a framing error.
|
* is lost and the first data byte will be lost by a framing error.
|
||||||
* To ensure the first start bit to be sent, prepend a zero byte (0x00)
|
* To ensure the first start bit to be sent, prepend a zero byte (0x00)
|
||||||
* to actual data bytes.
|
* to actual data bytes.
|
||||||
*/
|
*/
|
||||||
SERIAL_BIDIR_OD = 0 << 4,
|
// output configuration in BIDIR non-inverted mode
|
||||||
SERIAL_BIDIR_PP = 1 << 4,
|
// pushpull is used in UNIDIR or inverted mode by default
|
||||||
SERIAL_BIDIR_NOPULL = 1 << 5, // disable pulls in BIDIR RX mode
|
// SERIAL_BIDIR must be specified explicitly
|
||||||
SERIAL_BIDIR_PP_PD = 1 << 6, // PP mode, normall inverted, but with PullDowns, to fix SA after bidir issue fixed (#10220)
|
SERIAL_BIDIR_OD = 0 << 4, // default in BIDIR non-inverted mode
|
||||||
|
SERIAL_BIDIR_PP = 1 << 4, // force pushpull
|
||||||
|
|
||||||
|
SERIAL_PULL_DEFAULT = 0 << 5, // pulldown in inverted mode, pullup otherwise
|
||||||
|
SERIAL_PULL_NONE = 1 << 5, // disable pulls in RX or opendrain TX mode
|
||||||
|
// option for Smartaudio serial port - line is in MARK state when idle - break condition.
|
||||||
|
// DO NOT USE unless absolutely necessary
|
||||||
|
// SERIAL_PULL_NONE has precedence
|
||||||
|
SERIAL_PULL_SMARTAUDIO = 1 << 6, // set PULLDOWN on RX, even when not inverted.
|
||||||
|
|
||||||
// If this option is set then switch the TX line to input when not in use to detect it being pulled low
|
// If this option is set then switch the TX line to input when not in use to detect it being pulled low
|
||||||
|
// (and prevent powering external device by TX pin)
|
||||||
SERIAL_CHECK_TX = 1 << 7,
|
SERIAL_CHECK_TX = 1 << 7,
|
||||||
} portOptions_e;
|
} portOptions_e;
|
||||||
|
|
||||||
|
@ -90,32 +98,19 @@ typedef struct serialPort_s {
|
||||||
|
|
||||||
serialIdleCallbackPtr idleCallback;
|
serialIdleCallbackPtr idleCallback;
|
||||||
|
|
||||||
uint8_t identifier;
|
uint8_t identifier; // actually serialPortIdentifier_e; avoid circular header dependency
|
||||||
} serialPort_t;
|
} serialPort_t;
|
||||||
|
|
||||||
#define SERIAL_PORT_MAX_INDEX 11
|
|
||||||
#define SERIAL_UART_COUNT 10
|
|
||||||
#define SERIAL_LPUART_COUNT 1
|
|
||||||
|
|
||||||
typedef struct serialPinConfig_s {
|
typedef struct serialPinConfig_s {
|
||||||
ioTag_t ioTagTx[SERIAL_PORT_MAX_INDEX];
|
ioTag_t ioTagTx[RESOURCE_SERIAL_COUNT];
|
||||||
ioTag_t ioTagRx[SERIAL_PORT_MAX_INDEX];
|
ioTag_t ioTagRx[RESOURCE_SERIAL_COUNT];
|
||||||
ioTag_t ioTagInverter[SERIAL_PORT_MAX_INDEX];
|
#ifdef USE_INVERTER
|
||||||
|
ioTag_t ioTagInverter[RESOURCE_UART_COUNT]; // this array is only for UARTs.
|
||||||
|
#endif
|
||||||
} serialPinConfig_t;
|
} serialPinConfig_t;
|
||||||
|
|
||||||
PG_DECLARE(serialPinConfig_t, serialPinConfig);
|
PG_DECLARE(serialPinConfig_t, serialPinConfig);
|
||||||
|
|
||||||
#if defined(USE_SOFTSERIAL)
|
|
||||||
#define SOFTSERIAL_COUNT 2
|
|
||||||
|
|
||||||
typedef struct softSerialPinConfig_s {
|
|
||||||
ioTag_t ioTagTx[SOFTSERIAL_COUNT];
|
|
||||||
ioTag_t ioTagRx[SOFTSERIAL_COUNT];
|
|
||||||
} softSerialPinConfig_t;
|
|
||||||
|
|
||||||
PG_DECLARE(softSerialPinConfig_t, softSerialPinConfig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct serialPortVTable {
|
struct serialPortVTable {
|
||||||
void (*serialWrite)(serialPort_t *instance, uint8_t ch);
|
void (*serialWrite)(serialPort_t *instance, uint8_t ch);
|
||||||
|
|
||||||
|
|
39
src/main/drivers/serial_impl.c
Normal file
39
src/main/drivers/serial_impl.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
|
#include "serial.h"
|
||||||
|
#include "serial_impl.h"
|
||||||
|
|
||||||
|
// convert options into pin pull mode (up/down/none)
|
||||||
|
serialPullMode_t serialOptions_pull(portOptions_e options)
|
||||||
|
{
|
||||||
|
// handle SmartAudio first - different SA versions need different values
|
||||||
|
// add more cases here if necessary
|
||||||
|
if (options & SERIAL_PULL_SMARTAUDIO) {
|
||||||
|
#ifdef USE_SMARTAUDIO_NOPULLDOWN
|
||||||
|
return serialPullNone;
|
||||||
|
#else
|
||||||
|
return serialPullDown;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (options & SERIAL_PULL_NONE) {
|
||||||
|
return serialPullNone; // explicit nopull
|
||||||
|
} else if (options & SERIAL_INVERTED) {
|
||||||
|
return serialPullDown;
|
||||||
|
} else {
|
||||||
|
return serialPullUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is pushPull mode necessary
|
||||||
|
bool serialOptions_pushPull(portOptions_e options)
|
||||||
|
{
|
||||||
|
return options & (SERIAL_INVERTED | SERIAL_BIDIR_PP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
39
src/main/drivers/serial_impl.h
Normal file
39
src/main/drivers/serial_impl.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Betaflight.
|
||||||
|
*
|
||||||
|
* Betaflight is free software. You can redistribute this software
|
||||||
|
* and/or modify this software 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.
|
||||||
|
*
|
||||||
|
* Betaflight 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 this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* common functions related to serial port implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
// owner of Tx pin (+1 for Rx)
|
||||||
|
resourceOwner_e serialOwnerTxRx(serialPortIdentifier_e identifier);
|
||||||
|
// index for given owner
|
||||||
|
int serialOwnerIndex(serialPortIdentifier_e identifier);
|
||||||
|
|
||||||
|
typedef enum { serialPullNone = 0, serialPullDown = 1, serialPullUp = 2 } serialPullMode_t;
|
||||||
|
serialPullMode_t serialOptions_pull(portOptions_e options);
|
||||||
|
bool serialOptions_pushPull(portOptions_e options);
|
||||||
|
|
||||||
|
|
|
@ -34,159 +34,7 @@
|
||||||
|
|
||||||
#include "pg/pg_ids.h"
|
#include "pg/pg_ids.h"
|
||||||
|
|
||||||
// Backward compatibility for existing targets
|
#if defined(USE_UART) || defined(USE_LPUART) || defined(USE_SOFTSERIAL)
|
||||||
|
|
||||||
// Default pin (NONE).
|
|
||||||
|
|
||||||
#ifdef USE_UART1
|
|
||||||
# if !defined(UART1_RX_PIN)
|
|
||||||
# define UART1_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART1_TX_PIN)
|
|
||||||
# define UART1_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART1)
|
|
||||||
# define INVERTER_PIN_UART1 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART2
|
|
||||||
# if !defined(UART2_RX_PIN)
|
|
||||||
# define UART2_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART2_TX_PIN)
|
|
||||||
# define UART2_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART2)
|
|
||||||
# define INVERTER_PIN_UART2 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART3
|
|
||||||
# if !defined(UART3_RX_PIN)
|
|
||||||
# define UART3_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART3_TX_PIN)
|
|
||||||
# define UART3_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART3)
|
|
||||||
# define INVERTER_PIN_UART3 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART4
|
|
||||||
# if !defined(UART4_RX_PIN)
|
|
||||||
# define UART4_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART4_TX_PIN)
|
|
||||||
# define UART4_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART4)
|
|
||||||
# define INVERTER_PIN_UART4 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART5
|
|
||||||
# if !defined(UART5_RX_PIN)
|
|
||||||
# define UART5_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART5_TX_PIN)
|
|
||||||
# define UART5_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART5)
|
|
||||||
# define INVERTER_PIN_UART5 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART6
|
|
||||||
# if !defined(UART6_RX_PIN)
|
|
||||||
# define UART6_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART6_TX_PIN)
|
|
||||||
# define UART6_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART6)
|
|
||||||
# define INVERTER_PIN_UART6 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART7
|
|
||||||
# if !defined(UART7_RX_PIN)
|
|
||||||
# define UART7_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART7_TX_PIN)
|
|
||||||
# define UART7_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART7)
|
|
||||||
# define INVERTER_PIN_UART7 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART8
|
|
||||||
# if !defined(UART8_RX_PIN)
|
|
||||||
# define UART8_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART8_TX_PIN)
|
|
||||||
# define UART8_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART8)
|
|
||||||
# define INVERTER_PIN_UART8 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART9
|
|
||||||
# if !defined(UART9_RX_PIN)
|
|
||||||
# define UART9_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART9_TX_PIN)
|
|
||||||
# define UART9_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART9)
|
|
||||||
# define INVERTER_PIN_UART9 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART10
|
|
||||||
# if !defined(UART10_RX_PIN)
|
|
||||||
# define UART10_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(UART10_TX_PIN)
|
|
||||||
# define UART10_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_UART10)
|
|
||||||
# define INVERTER_PIN_UART10 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
|
||||||
# if !defined(LPUART1_RX_PIN)
|
|
||||||
# define LPUART1_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(LPUART1_TX_PIN)
|
|
||||||
# define LPUART1_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(INVERTER_PIN_LPUART1)
|
|
||||||
# define INVERTER_PIN_LPUART1 NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
# if !defined(SOFTSERIAL1_RX_PIN)
|
|
||||||
# define SOFTSERIAL1_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(SOFTSERIAL1_TX_PIN)
|
|
||||||
# define SOFTSERIAL1_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if !defined(SOFTSERIAL2_RX_PIN)
|
|
||||||
# define SOFTSERIAL2_RX_PIN NONE
|
|
||||||
# endif
|
|
||||||
# if !defined(SOFTSERIAL2_TX_PIN)
|
|
||||||
# define SOFTSERIAL2_TX_PIN NONE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_UART) || defined(USE_SOFTSERIAL)
|
|
||||||
typedef struct serialDefaultPin_s {
|
typedef struct serialDefaultPin_s {
|
||||||
serialPortIdentifier_e ident;
|
serialPortIdentifier_e ident;
|
||||||
ioTag_t rxIO, txIO, inverterIO;
|
ioTag_t rxIO, txIO, inverterIO;
|
||||||
|
@ -224,7 +72,13 @@ static const serialDefaultPin_t serialDefaultPin[] = {
|
||||||
{ SERIAL_PORT_USART10, IO_TAG(UART10_RX_PIN), IO_TAG(UART10_TX_PIN), IO_TAG(INVERTER_PIN_UART10) },
|
{ SERIAL_PORT_USART10, IO_TAG(UART10_RX_PIN), IO_TAG(UART10_TX_PIN), IO_TAG(INVERTER_PIN_UART10) },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
{ SERIAL_PORT_LPUART1, IO_TAG(LPUART1_RX_PIN), IO_TAG(LPUART1_TX_PIN), IO_TAG(INVERTER_PIN_LPUART1) },
|
{ SERIAL_PORT_LPUART1, IO_TAG(LPUART1_RX_PIN), IO_TAG(LPUART1_TX_PIN), IO_TAG(NONE) },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL1
|
||||||
|
{ SERIAL_PORT_SOFTSERIAL1, IO_TAG(SOFTSERIAL1_RX_PIN), IO_TAG(SOFTSERIAL1_TX_PIN), IO_TAG(NONE) },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL2
|
||||||
|
{ SERIAL_PORT_SOFTSERIAL2, IO_TAG(SOFTSERIAL2_RX_PIN), IO_TAG(SOFTSERIAL2_TX_PIN), IO_TAG(NONE) },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -232,38 +86,21 @@ PG_REGISTER_WITH_RESET_FN(serialPinConfig_t, serialPinConfig, PG_SERIAL_PIN_CONF
|
||||||
|
|
||||||
void pgResetFn_serialPinConfig(serialPinConfig_t *serialPinConfig)
|
void pgResetFn_serialPinConfig(serialPinConfig_t *serialPinConfig)
|
||||||
{
|
{
|
||||||
for (size_t index = 0 ; index < ARRAYLEN(serialDefaultPin) ; index++) {
|
for (const serialDefaultPin_t *defpin = serialDefaultPin; defpin < ARRAYEND(serialDefaultPin); defpin++) {
|
||||||
const serialDefaultPin_t *defpin = &serialDefaultPin[index];
|
const int resourceIndex = serialResourceIndex(defpin->ident);
|
||||||
serialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_INDEX(defpin->ident)] = defpin->rxIO;
|
if (resourceIndex >= 0) {
|
||||||
serialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_INDEX(defpin->ident)] = defpin->txIO;
|
serialPinConfig->ioTagRx[resourceIndex] = defpin->rxIO;
|
||||||
serialPinConfig->ioTagInverter[SERIAL_PORT_IDENTIFIER_TO_INDEX(defpin->ident)] = defpin->inverterIO;
|
serialPinConfig->ioTagTx[resourceIndex] = defpin->txIO;
|
||||||
|
#if defined(USE_INVERTER)
|
||||||
|
// LPUART/SOFTSERIAL do not need/support inverter
|
||||||
|
if (resourceIndex < (int)ARRAYLEN(serialPinConfig->ioTagInverter)) {
|
||||||
|
serialPinConfig->ioTagInverter[resourceIndex] = defpin->inverterIO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_SOFTSERIAL)
|
|
||||||
typedef struct softSerialDefaultPin_s {
|
|
||||||
serialPortIdentifier_e ident;
|
|
||||||
ioTag_t rxIO, txIO;
|
|
||||||
} softSerialDefaultPin_t;
|
|
||||||
|
|
||||||
static const softSerialDefaultPin_t softSerialDefaultPin[SOFTSERIAL_COUNT] = {
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
{ SERIAL_PORT_SOFTSERIAL1, IO_TAG(SOFTSERIAL1_RX_PIN), IO_TAG(SOFTSERIAL1_TX_PIN) },
|
|
||||||
{ SERIAL_PORT_SOFTSERIAL2, IO_TAG(SOFTSERIAL2_RX_PIN), IO_TAG(SOFTSERIAL2_TX_PIN) },
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
PG_REGISTER_WITH_RESET_FN(softSerialPinConfig_t, softSerialPinConfig, PG_SOFTSERIAL_PIN_CONFIG, 0);
|
|
||||||
|
|
||||||
void pgResetFn_softSerialPinConfig(softSerialPinConfig_t *softSerialPinConfig)
|
|
||||||
{
|
|
||||||
for (size_t index = 0 ; index < ARRAYLEN(softSerialDefaultPin) ; index++) {
|
|
||||||
const softSerialDefaultPin_t *defpin = &softSerialDefaultPin[index];
|
|
||||||
softSerialPinConfig->ioTagRx[SOFTSERIAL_PORT_IDENTIFIER_TO_INDEX(defpin->ident)] = defpin->rxIO;
|
|
||||||
softSerialPinConfig->ioTagTx[SOFTSERIAL_PORT_IDENTIFIER_TO_INDEX(defpin->ident)] = defpin->txIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
40
src/main/drivers/serial_resource.h
Normal file
40
src/main/drivers/serial_resource.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Betaflight.
|
||||||
|
*
|
||||||
|
* Betaflight is free software. You can redistribute this software
|
||||||
|
* and/or modify this software 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.
|
||||||
|
*
|
||||||
|
* Betaflight 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 this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
#defines used for serial port resource access (pin/dma/inversion)
|
||||||
|
target/serial_post.h normalizes enabled port definitions (and port counts),
|
||||||
|
values are just renamed here
|
||||||
|
*/
|
||||||
|
|
||||||
|
// use _MAX value here, resource command needs linear mapping
|
||||||
|
// (UART8 is always at index RESOURCE_UART_OFFSET + 7, no matter which other ports are enabled)
|
||||||
|
#define RESOURCE_UART_COUNT SERIAL_UART_MAX
|
||||||
|
#define RESOURCE_LPUART_COUNT SERIAL_LPUART_MAX
|
||||||
|
#define RESOURCE_SOFTSERIAL_COUNT SERIAL_SOFTSERIAL_MAX
|
||||||
|
#define RESOURCE_SERIAL_COUNT (RESOURCE_UART_COUNT + RESOURCE_LPUART_COUNT + RESOURCE_SOFTSERIAL_COUNT)
|
||||||
|
// resources are stored in one array, in UART, LPUART, SOFTSERIAL order. Code does assume this ordering,
|
||||||
|
// do not change it without adapting relevant code.
|
||||||
|
#define RESOURCE_UART_OFFSET 0
|
||||||
|
#define RESOURCE_LPUART_OFFSET RESOURCE_UART_COUNT
|
||||||
|
#define RESOURCE_SOFTSERIAL_OFFSET (RESOURCE_UART_COUNT + RESOURCE_LPUART_COUNT)
|
|
@ -37,9 +37,12 @@
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
#include "drivers/nvic.h"
|
#include "drivers/nvic.h"
|
||||||
#include "drivers/io.h"
|
#include "drivers/io.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
#include "drivers/serial_impl.h"
|
||||||
#include "drivers/timer.h"
|
#include "drivers/timer.h"
|
||||||
|
|
||||||
#include "serial_softserial.h"
|
#include "serial_softserial.h"
|
||||||
|
@ -47,8 +50,6 @@
|
||||||
#define RX_TOTAL_BITS 10
|
#define RX_TOTAL_BITS 10
|
||||||
#define TX_TOTAL_BITS 10
|
#define TX_TOTAL_BITS 10
|
||||||
|
|
||||||
#define MAX_SOFTSERIAL_PORTS 2
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TIMER_MODE_SINGLE,
|
TIMER_MODE_SINGLE,
|
||||||
TIMER_MODE_DUAL,
|
TIMER_MODE_DUAL,
|
||||||
|
@ -87,7 +88,6 @@ typedef struct softSerial_s {
|
||||||
uint16_t transmissionErrors;
|
uint16_t transmissionErrors;
|
||||||
uint16_t receiveErrors;
|
uint16_t receiveErrors;
|
||||||
|
|
||||||
uint8_t softSerialPortIndex;
|
|
||||||
timerMode_e timerMode;
|
timerMode_e timerMode;
|
||||||
|
|
||||||
timerOvrHandlerRec_t overCb;
|
timerOvrHandlerRec_t overCb;
|
||||||
|
@ -95,23 +95,16 @@ typedef struct softSerial_s {
|
||||||
} softSerial_t;
|
} softSerial_t;
|
||||||
|
|
||||||
static const struct serialPortVTable softSerialVTable; // Forward
|
static const struct serialPortVTable softSerialVTable; // Forward
|
||||||
|
// SERIAL_SOFTSERIAL_COUNT is fine, softserial ports must start from 1 and be continuous
|
||||||
static softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS];
|
static softSerial_t softSerialPorts[SERIAL_SOFTSERIAL_COUNT];
|
||||||
|
|
||||||
void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture);
|
void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture);
|
||||||
void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
|
void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
|
||||||
|
|
||||||
static void setTxSignal(softSerial_t *softSerial, uint8_t state)
|
typedef enum { IDLE = ENABLE, MARK = DISABLE } SerialTxState_e;
|
||||||
|
static void setTxSignal(softSerial_t *softSerial, SerialTxState_e state)
|
||||||
{
|
{
|
||||||
if (softSerial->port.options & SERIAL_INVERTED) {
|
IOWrite(softSerial->txIO, (softSerial->port.options & SERIAL_INVERTED) ? !state : state);
|
||||||
state = !state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state) {
|
|
||||||
IOHi(softSerial->txIO);
|
|
||||||
} else {
|
|
||||||
IOLo(softSerial->txIO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialEnableCC(softSerial_t *softSerial)
|
static void serialEnableCC(softSerial_t *softSerial)
|
||||||
|
@ -123,15 +116,13 @@ static void serialEnableCC(softSerial_t *softSerial)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// switch to receive mode
|
||||||
static void serialInputPortActivate(softSerial_t *softSerial)
|
static void serialInputPortActivate(softSerial_t *softSerial)
|
||||||
{
|
{
|
||||||
if (softSerial->port.options & SERIAL_INVERTED) {
|
const serialPullMode_t pull = serialOptions_pull(softSerial->port.options);
|
||||||
const uint8_t pinConfig = (softSerial->port.options & SERIAL_BIDIR_NOPULL) ? IOCFG_AF_PP : IOCFG_AF_PP_PD;
|
const uint8_t pinConfig = ((const uint8_t[]){IOCFG_AF_PP, IOCFG_AF_PP_PD, IOCFG_AF_PP_UP})[pull];
|
||||||
IOConfigGPIOAF(softSerial->rxIO, pinConfig, softSerial->timerHardware->alternateFunction);
|
// softserial can easily support opendrain mode, but it is not implemented
|
||||||
} else {
|
IOConfigGPIOAF(softSerial->rxIO, pinConfig, softSerial->timerHardware->alternateFunction);
|
||||||
const uint8_t pinConfig = (softSerial->port.options & SERIAL_BIDIR_NOPULL) ? IOCFG_AF_PP : IOCFG_AF_PP_UP;
|
|
||||||
IOConfigGPIOAF(softSerial->rxIO, pinConfig, softSerial->timerHardware->alternateFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
softSerial->rxActive = true;
|
softSerial->rxActive = true;
|
||||||
softSerial->isSearchingForStartBit = true;
|
softSerial->isSearchingForStartBit = true;
|
||||||
|
@ -151,25 +142,27 @@ static void serialInputPortDeActivate(softSerial_t *softSerial)
|
||||||
#else
|
#else
|
||||||
TIM_CCxCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_Disable);
|
TIM_CCxCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_Disable);
|
||||||
#endif
|
#endif
|
||||||
|
IOConfigGPIO(softSerial->rxIO, IOCFG_IN_FLOATING); // leave AF mode; serialOutputPortActivate will follow immediately
|
||||||
IOConfigGPIO(softSerial->rxIO, IOCFG_IN_FLOATING);
|
|
||||||
softSerial->rxActive = false;
|
softSerial->rxActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialOutputPortActivate(softSerial_t *softSerial)
|
static void serialOutputPortActivate(softSerial_t *softSerial)
|
||||||
{
|
{
|
||||||
if (softSerial->exTimerHardware)
|
if (softSerial->exTimerHardware) {
|
||||||
IOConfigGPIOAF(softSerial->txIO, IOCFG_OUT_PP, softSerial->exTimerHardware->alternateFunction);
|
IOConfigGPIOAF(softSerial->txIO, IOCFG_OUT_PP, softSerial->exTimerHardware->alternateFunction);
|
||||||
else
|
} else {
|
||||||
IOConfigGPIO(softSerial->txIO, IOCFG_OUT_PP);
|
IOConfigGPIO(softSerial->txIO, IOCFG_OUT_PP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialOutputPortDeActivate(softSerial_t *softSerial)
|
static void serialOutputPortDeActivate(softSerial_t *softSerial)
|
||||||
{
|
{
|
||||||
if (softSerial->exTimerHardware)
|
if (softSerial->exTimerHardware) {
|
||||||
|
// TODO: there in no AF associated with input port
|
||||||
IOConfigGPIOAF(softSerial->txIO, IOCFG_IN_FLOATING, softSerial->exTimerHardware->alternateFunction);
|
IOConfigGPIOAF(softSerial->txIO, IOCFG_IN_FLOATING, softSerial->exTimerHardware->alternateFunction);
|
||||||
else
|
} else {
|
||||||
IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING);
|
IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isTimerPeriodTooLarge(uint32_t timerPeriod)
|
static bool isTimerPeriodTooLarge(uint32_t timerPeriod)
|
||||||
|
@ -183,19 +176,10 @@ static void serialTimerConfigureTimebase(const timerHardware_t *timerHardwarePtr
|
||||||
uint32_t clock = baseClock;
|
uint32_t clock = baseClock;
|
||||||
uint32_t timerPeriod;
|
uint32_t timerPeriod;
|
||||||
|
|
||||||
do {
|
while (timerPeriod = clock / baud, isTimerPeriodTooLarge(timerPeriod) && clock > 1) {
|
||||||
timerPeriod = clock / baud;
|
clock = clock / 2; // minimum baudrate is < 1200
|
||||||
if (isTimerPeriodTooLarge(timerPeriod)) {
|
}
|
||||||
if (clock > 1) {
|
timerConfigure(timerHardwarePtr, timerPeriod, clock);
|
||||||
clock = clock / 2; // this is wrong - mhz stays the same ... This will double baudrate until ok (but minimum baudrate is < 1200)
|
|
||||||
} else {
|
|
||||||
// TODO unable to continue, unable to determine clock and timerPeriods for the given baud
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} while (isTimerPeriodTooLarge(timerPeriod));
|
|
||||||
|
|
||||||
timerConfigure(timerHardwarePtr, timerPeriod, baseClock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resetBuffers(softSerial_t *softSerial)
|
static void resetBuffers(softSerial_t *softSerial)
|
||||||
|
@ -211,15 +195,32 @@ static void resetBuffers(softSerial_t *softSerial)
|
||||||
softSerial->port.txBufferHead = 0;
|
softSerial->port.txBufferHead = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baud, portMode_e mode, portOptions_e options)
|
softSerial_t* softSerialFromIdentifier(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
softSerial_t *softSerial = &(softSerialPorts[portIndex]);
|
if (identifier >= SERIAL_PORT_SOFTSERIAL1 && identifier < SERIAL_PORT_SOFTSERIAL1 + SERIAL_SOFTSERIAL_COUNT) {
|
||||||
|
return &softSerialPorts[identifier - SERIAL_PORT_SOFTSERIAL1];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ioTag_t tagRx = softSerialPinConfig()->ioTagRx[portIndex];
|
serialPort_t *softSerialOpen(serialPortIdentifier_e identifier, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baud, portMode_e mode, portOptions_e options)
|
||||||
ioTag_t tagTx = softSerialPinConfig()->ioTagTx[portIndex];
|
{
|
||||||
|
softSerial_t *softSerial = softSerialFromIdentifier(identifier);
|
||||||
|
if (!softSerial) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// fill identifier early, so initialization code can use it
|
||||||
|
softSerial->port.identifier = identifier;
|
||||||
|
|
||||||
const timerHardware_t *timerTx = timerAllocate(tagTx, OWNER_SOFTSERIAL_TX, RESOURCE_INDEX(portIndex));
|
const int resourceIndex = serialResourceIndex(identifier);
|
||||||
const timerHardware_t *timerRx = (tagTx == tagRx) ? timerTx : timerAllocate(tagRx, OWNER_SOFTSERIAL_RX, RESOURCE_INDEX(portIndex));
|
const resourceOwner_e ownerTxRx = serialOwnerTxRx(identifier); // rx is always +1
|
||||||
|
const int ownerIndex = serialOwnerIndex(identifier);
|
||||||
|
|
||||||
|
const ioTag_t tagRx = serialPinConfig()->ioTagRx[resourceIndex];
|
||||||
|
const ioTag_t tagTx = serialPinConfig()->ioTagTx[resourceIndex];
|
||||||
|
|
||||||
|
const timerHardware_t *timerTx = timerAllocate(tagTx, ownerTxRx, ownerIndex);
|
||||||
|
const timerHardware_t *timerRx = (tagTx == tagRx) ? timerTx : timerAllocate(tagRx, ownerTxRx + 1, ownerIndex);
|
||||||
|
|
||||||
IO_t rxIO = IOGetByTag(tagRx);
|
IO_t rxIO = IOGetByTag(tagRx);
|
||||||
IO_t txIO = IOGetByTag(tagTx);
|
IO_t txIO = IOGetByTag(tagTx);
|
||||||
|
@ -227,7 +228,7 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
if (options & SERIAL_BIDIR) {
|
if (options & SERIAL_BIDIR) {
|
||||||
// If RX and TX pins are both assigned, we CAN use either with a timer.
|
// If RX and TX pins are both assigned, we CAN use either with a timer.
|
||||||
// However, for consistency with hardware UARTs, we only use TX pin,
|
// However, for consistency with hardware UARTs, we only use TX pin,
|
||||||
// and this pin must have a timer, and it should not be N-Channel.
|
// and this pin must have a timer, and it must not be N-Channel.
|
||||||
if (!timerTx || (timerTx->output & TIMER_OUTPUT_N_CHANNEL)) {
|
if (!timerTx || (timerTx->output & TIMER_OUTPUT_N_CHANNEL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -235,10 +236,10 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
softSerial->timerHardware = timerTx;
|
softSerial->timerHardware = timerTx;
|
||||||
softSerial->txIO = txIO;
|
softSerial->txIO = txIO;
|
||||||
softSerial->rxIO = txIO;
|
softSerial->rxIO = txIO;
|
||||||
IOInit(txIO, OWNER_SOFTSERIAL_TX, RESOURCE_INDEX(portIndex));
|
IOInit(txIO, ownerTxRx, ownerIndex);
|
||||||
} else {
|
} else {
|
||||||
if (mode & MODE_RX) {
|
if (mode & MODE_RX) {
|
||||||
// Need a pin & a timer on RX. Channel should not be N-Channel.
|
// Need a pin & a timer on RX. Channel must not be N-Channel.
|
||||||
if (!timerRx || (timerRx->output & TIMER_OUTPUT_N_CHANNEL)) {
|
if (!timerRx || (timerRx->output & TIMER_OUTPUT_N_CHANNEL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -246,27 +247,29 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
softSerial->rxIO = rxIO;
|
softSerial->rxIO = rxIO;
|
||||||
softSerial->timerHardware = timerRx;
|
softSerial->timerHardware = timerRx;
|
||||||
if (!((mode & MODE_TX) && rxIO == txIO)) {
|
if (!((mode & MODE_TX) && rxIO == txIO)) {
|
||||||
IOInit(rxIO, OWNER_SOFTSERIAL_RX, RESOURCE_INDEX(portIndex));
|
// RX only on pin
|
||||||
|
IOInit(rxIO, ownerTxRx + 1, ownerIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode & MODE_TX) {
|
if (mode & MODE_TX) {
|
||||||
// Need a pin on TX
|
// Need a pin on TX
|
||||||
if (!tagTx)
|
if (!txIO)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
softSerial->txIO = txIO;
|
softSerial->txIO = txIO;
|
||||||
|
|
||||||
if (!(mode & MODE_RX)) {
|
if (!(mode & MODE_RX)) {
|
||||||
// TX Simplex, must have a timer
|
// TX Simplex, must have a timer
|
||||||
if (!timerTx)
|
if (!timerTx) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
softSerial->timerHardware = timerTx;
|
softSerial->timerHardware = timerTx;
|
||||||
} else {
|
} else {
|
||||||
// Duplex
|
// Duplex, use timerTx if available
|
||||||
softSerial->exTimerHardware = timerTx;
|
softSerial->exTimerHardware = timerTx;
|
||||||
}
|
}
|
||||||
IOInit(txIO, OWNER_SOFTSERIAL_TX, RESOURCE_INDEX(portIndex));
|
IOInit(txIO, ownerTxRx, ownerIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,8 +282,6 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
|
|
||||||
resetBuffers(softSerial);
|
resetBuffers(softSerial);
|
||||||
|
|
||||||
softSerial->softSerialPortIndex = portIndex;
|
|
||||||
|
|
||||||
softSerial->transmissionErrors = 0;
|
softSerial->transmissionErrors = 0;
|
||||||
softSerial->receiveErrors = 0;
|
softSerial->receiveErrors = 0;
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
|
|
||||||
if (!(options & SERIAL_BIDIR)) {
|
if (!(options & SERIAL_BIDIR)) {
|
||||||
serialOutputPortActivate(softSerial);
|
serialOutputPortActivate(softSerial);
|
||||||
setTxSignal(softSerial, ENABLE);
|
setTxSignal(softSerial, IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
serialInputPortActivate(softSerial);
|
serialInputPortActivate(softSerial);
|
||||||
|
@ -332,14 +333,12 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
|
||||||
|
|
||||||
void processTxState(softSerial_t *softSerial)
|
void processTxState(softSerial_t *softSerial)
|
||||||
{
|
{
|
||||||
uint8_t mask;
|
|
||||||
|
|
||||||
if (!softSerial->isTransmittingData) {
|
if (!softSerial->isTransmittingData) {
|
||||||
if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) {
|
if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) {
|
||||||
// Transmit buffer empty.
|
// Transmit buffer empty.
|
||||||
// Start listening if not already in if half-duplex
|
// Switch to RX mode if not already listening and running in half-duplex mode
|
||||||
if (!softSerial->rxActive && softSerial->port.options & SERIAL_BIDIR) {
|
if (!softSerial->rxActive && softSerial->port.options & SERIAL_BIDIR) {
|
||||||
serialOutputPortDeActivate(softSerial);
|
serialOutputPortDeActivate(softSerial); // TODO: not necessary
|
||||||
serialInputPortActivate(softSerial);
|
serialInputPortActivate(softSerial);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -352,7 +351,7 @@ void processTxState(softSerial_t *softSerial)
|
||||||
}
|
}
|
||||||
|
|
||||||
// build internal buffer, MSB = Stop Bit (1) + data bits (MSB to LSB) + start bit(0) LSB
|
// build internal buffer, MSB = Stop Bit (1) + data bits (MSB to LSB) + start bit(0) LSB
|
||||||
softSerial->internalTxBuffer = (1 << (TX_TOTAL_BITS - 1)) | (byteToSend << 1);
|
softSerial->internalTxBuffer = (1 << (TX_TOTAL_BITS - 1)) | (byteToSend << 1) | 0;
|
||||||
softSerial->bitsLeftToTransmit = TX_TOTAL_BITS;
|
softSerial->bitsLeftToTransmit = TX_TOTAL_BITS;
|
||||||
softSerial->isTransmittingData = true;
|
softSerial->isTransmittingData = true;
|
||||||
|
|
||||||
|
@ -365,16 +364,18 @@ void processTxState(softSerial_t *softSerial)
|
||||||
// and continuing here may cause bit period to decrease causing sampling errors
|
// and continuing here may cause bit period to decrease causing sampling errors
|
||||||
// at the receiver under high rates.
|
// at the receiver under high rates.
|
||||||
// Note that there will be (little less than) 1-bit delay; take it as "turn around time".
|
// Note that there will be (little less than) 1-bit delay; take it as "turn around time".
|
||||||
// XXX We may be able to reload counter and continue. (Future work.)
|
// This time is important in noninverted pulldown bidir mode (SmartAudio).
|
||||||
|
// During this period, TX pin is in IDLE state so next startbit (MARK) can be detected
|
||||||
|
// XXX Otherwise, we may be able to reload counter and continue. (Future work.)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (softSerial->bitsLeftToTransmit) {
|
if (softSerial->bitsLeftToTransmit) {
|
||||||
mask = softSerial->internalTxBuffer & 1;
|
const bool bit = softSerial->internalTxBuffer & 1;
|
||||||
softSerial->internalTxBuffer >>= 1;
|
softSerial->internalTxBuffer >>= 1;
|
||||||
|
|
||||||
setTxSignal(softSerial, mask);
|
setTxSignal(softSerial, bit);
|
||||||
softSerial->bitsLeftToTransmit--;
|
softSerial->bitsLeftToTransmit--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -390,8 +391,7 @@ enum {
|
||||||
void applyChangedBits(softSerial_t *softSerial)
|
void applyChangedBits(softSerial_t *softSerial)
|
||||||
{
|
{
|
||||||
if (softSerial->rxEdge == TRAILING) {
|
if (softSerial->rxEdge == TRAILING) {
|
||||||
uint8_t bitToSet;
|
for (unsigned bitToSet = softSerial->rxLastLeadingEdgeAtBitIndex; bitToSet < softSerial->rxBitIndex; bitToSet++) {
|
||||||
for (bitToSet = softSerial->rxLastLeadingEdgeAtBitIndex; bitToSet < softSerial->rxBitIndex; bitToSet++) {
|
|
||||||
softSerial->internalRxBuffer |= 1 << bitToSet;
|
softSerial->internalRxBuffer |= 1 << bitToSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,12 +477,13 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
|
||||||
UNUSED(capture);
|
UNUSED(capture);
|
||||||
|
|
||||||
softSerial_t *self = container_of(cbRec, softSerial_t, edgeCb);
|
softSerial_t *self = container_of(cbRec, softSerial_t, edgeCb);
|
||||||
bool inverted = self->port.options & SERIAL_INVERTED;
|
|
||||||
|
|
||||||
if ((self->port.mode & MODE_RX) == 0) {
|
if ((self->port.mode & MODE_RX) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool inverted = self->port.options & SERIAL_INVERTED;
|
||||||
|
|
||||||
if (self->isSearchingForStartBit) {
|
if (self->isSearchingForStartBit) {
|
||||||
// Synchronize the bit timing so that it will interrupt at the center
|
// Synchronize the bit timing so that it will interrupt at the center
|
||||||
// of the bit period.
|
// of the bit period.
|
||||||
|
|
|
@ -22,12 +22,9 @@
|
||||||
|
|
||||||
#define SOFTSERIAL_BUFFER_SIZE 256
|
#define SOFTSERIAL_BUFFER_SIZE 256
|
||||||
|
|
||||||
typedef enum {
|
#include "io/serial.h"
|
||||||
SOFTSERIAL1 = 0,
|
|
||||||
SOFTSERIAL2
|
|
||||||
} softSerialPortIndex_e;
|
|
||||||
|
|
||||||
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baud, portMode_e mode, portOptions_e options);
|
serialPort_t *softSerialOpen(serialPortIdentifier_e identifier, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baud, portMode_e mode, portOptions_e options);
|
||||||
|
|
||||||
// serialPort API
|
// serialPort API
|
||||||
void softSerialWriteByte(serialPort_t *instance, uint8_t ch);
|
void softSerialWriteByte(serialPort_t *instance, uint8_t ch);
|
||||||
|
|
|
@ -38,10 +38,13 @@
|
||||||
#include <common/maths.h>
|
#include <common/maths.h>
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
#include "drivers/dma.h"
|
#include "drivers/dma.h"
|
||||||
#include "drivers/dma_reqmap.h"
|
#include "drivers/dma_reqmap.h"
|
||||||
#include "drivers/rcc.h"
|
#include "drivers/rcc.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
#include "drivers/serial_impl.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
|
@ -63,13 +66,10 @@
|
||||||
#error Undefined UART_{TX,RX}_BUFFER_ATTRIBUTE for this MCU
|
#error Undefined UART_{TX,RX}_BUFFER_ATTRIBUTE for this MCU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UART_BUFFERS(n) \
|
#define UART_BUFFERS(n) \
|
||||||
UART_BUFFER(UART_TX_BUFFER_ATTRIBUTE, n, T); \
|
UART_BUFFER(UART_TX_BUFFER_ATTRIBUTE, n, T); \
|
||||||
UART_BUFFER(UART_RX_BUFFER_ATTRIBUTE, n, R); struct dummy_s
|
UART_BUFFER(UART_RX_BUFFER_ATTRIBUTE, n, R); struct dummy_s \
|
||||||
|
/**/
|
||||||
#define LPUART_BUFFERS(n) \
|
|
||||||
LPUART_BUFFER(UART_TX_BUFFER_ATTRIBUTE, n, T); \
|
|
||||||
LPUART_BUFFER(UART_RX_BUFFER_ATTRIBUTE, n, R); struct dummy_s
|
|
||||||
|
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
UART_BUFFERS(1);
|
UART_BUFFERS(1);
|
||||||
|
@ -112,22 +112,103 @@ UART_BUFFERS(10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
LPUART_BUFFERS(1);
|
UART_BUFFERS(Lp1); // TODO - maybe some other naming scheme ?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef UART_BUFFERS
|
#undef UART_BUFFERS
|
||||||
|
|
||||||
serialPort_t *uartOpen(UARTDevice_e device, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
// store only devices configured for target (USE_UARTx)
|
||||||
|
// some entries may be unused, for example because of pin configuration
|
||||||
|
// uartDeviceIdx_e is direct index into this table
|
||||||
|
FAST_DATA_ZERO_INIT uartDevice_t uartDevice[UARTDEV_COUNT];
|
||||||
|
|
||||||
|
// map serialPortIdentifier_e to uartDeviceIdx_e
|
||||||
|
uartDeviceIdx_e uartDeviceIdxFromIdentifier(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
uartPort_t *uartPort = serialUART(device, baudRate, mode, options);
|
#ifdef USE_LPUART1
|
||||||
|
if (identifier == SERIAL_PORT_LPUART1) {
|
||||||
if (!uartPort)
|
return UARTDEV_LP1;
|
||||||
return (serialPort_t *)uartPort;
|
}
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartPort->txDMAEmpty = true;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1 // TODO ...
|
||||||
|
// store +1 in table - unset values default to 0
|
||||||
|
// 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_UART1
|
||||||
|
_R(SERIAL_PORT_USART1, UARTDEV_1),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
|
_R(SERIAL_PORT_USART2, UARTDEV_2),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
|
_R(SERIAL_PORT_USART3, UARTDEV_3),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
|
_R(SERIAL_PORT_UART4, UARTDEV_4),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
|
_R(SERIAL_PORT_UART5, UARTDEV_5),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
|
_R(SERIAL_PORT_USART6, UARTDEV_6),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART7
|
||||||
|
_R(SERIAL_PORT_USART7, UARTDEV_7),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART8
|
||||||
|
_R(SERIAL_PORT_USART8, UARTDEV_8),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART9
|
||||||
|
_R(SERIAL_PORT_UART9, UARTDEV_9),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART10
|
||||||
|
_R(SERIAL_PORT_USART10, UARTDEV_10),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#undef _R
|
||||||
|
if (identifier >= 0 && identifier < (int)ARRAYLEN(uartMap)) {
|
||||||
|
// UART case, but given USE_UARTx may not be defined
|
||||||
|
return uartMap[identifier] ? uartMap[identifier] - 1 : UARTDEV_INVALID;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
const int idx = identifier - SERIAL_PORT_USART1;
|
||||||
|
if (idx >= 0 && idx < SERIAL_UART_MAX) {
|
||||||
|
if (BIT(idx) & SERIAL_UART_MASK) {
|
||||||
|
// return number of enabled UART ports smaller than idx
|
||||||
|
return popcount((BIT(idx) - 1) & SERIAL_UART_MASK);
|
||||||
|
} else {
|
||||||
|
return UARTDEV_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// neither LPUART nor UART
|
||||||
|
return UARTDEV_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uartDevice_t *uartDeviceFromIdentifier(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
const uartDeviceIdx_e deviceIdx = uartDeviceIdxFromIdentifier(identifier);
|
||||||
|
return deviceIdx != UARTDEV_INVALID ? &uartDevice[deviceIdx] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
serialPort_t *uartOpen(serialPortIdentifier_e identifier, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
||||||
|
{
|
||||||
|
uartDevice_t *uartDevice = uartDeviceFromIdentifier(identifier);
|
||||||
|
if (!uartDevice) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// fill identifier early, so initialization code can use it
|
||||||
|
uartDevice->port.port.identifier = identifier;
|
||||||
|
|
||||||
|
uartPort_t *uartPort = serialUART(uartDevice, baudRate, mode, options);
|
||||||
|
if (!uartPort) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// common serial initialisation code should move to serialPort::init()
|
// common serial initialisation code should move to serialPort::init()
|
||||||
uartPort->port.rxBufferHead = uartPort->port.rxBufferTail = 0;
|
uartPort->port.rxBufferHead = uartPort->port.rxBufferTail = 0;
|
||||||
uartPort->port.txBufferHead = uartPort->port.txBufferTail = 0;
|
uartPort->port.txBufferHead = uartPort->port.txBufferTail = 0;
|
||||||
|
@ -381,6 +462,7 @@ const struct serialPortVTable uartVTable[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO - move to serial_uart_hw.c
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
void uartConfigureDma(uartDevice_t *uartdev)
|
void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
{
|
{
|
||||||
|
@ -388,11 +470,22 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
const uartHardware_t *hardware = uartdev->hardware;
|
||||||
|
|
||||||
#ifdef USE_DMA_SPEC
|
#ifdef USE_DMA_SPEC
|
||||||
UARTDevice_e device = hardware->device;
|
const serialPortIdentifier_e uartPortIdentifier = hardware->identifier;
|
||||||
const dmaChannelSpec_t *dmaChannelSpec;
|
const uartDeviceIdx_e uartDeviceIdx = uartDeviceIdxFromIdentifier(uartPortIdentifier);
|
||||||
|
if (uartDeviceIdx == UARTDEV_INVALID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int resourceIdx = serialResourceIndex(uartPortIdentifier);
|
||||||
|
const int ownerIndex = serialOwnerIndex(uartPortIdentifier);
|
||||||
|
const resourceOwner_e ownerTxRx = serialOwnerTxRx(uartPortIdentifier); // rx is always +1
|
||||||
|
|
||||||
if (serialUartConfig(device)->txDmaopt != DMA_OPT_UNUSED) {
|
const dmaChannelSpec_t *dmaChannelSpec;
|
||||||
dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_UART_TX, device, serialUartConfig(device)->txDmaopt);
|
const serialUartConfig_t *cfg = serialUartConfig(resourceIdx);
|
||||||
|
if (!cfg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cfg->txDmaopt != DMA_OPT_UNUSED) {
|
||||||
|
dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_UART_TX, uartDeviceIdx, cfg->txDmaopt);
|
||||||
if (dmaChannelSpec) {
|
if (dmaChannelSpec) {
|
||||||
uartPort->txDMAResource = dmaChannelSpec->ref;
|
uartPort->txDMAResource = dmaChannelSpec->ref;
|
||||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
||||||
|
@ -403,8 +496,8 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialUartConfig(device)->rxDmaopt != DMA_OPT_UNUSED) {
|
if (cfg->rxDmaopt != DMA_OPT_UNUSED) {
|
||||||
dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_UART_RX, device, serialUartConfig(device)->txDmaopt);
|
dmaChannelSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_UART_RX, uartDeviceIdx, cfg->txDmaopt);
|
||||||
if (dmaChannelSpec) {
|
if (dmaChannelSpec) {
|
||||||
uartPort->rxDMAResource = dmaChannelSpec->ref;
|
uartPort->rxDMAResource = dmaChannelSpec->ref;
|
||||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
||||||
|
@ -414,7 +507,7 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else /* USE_DMA_SPEC */
|
||||||
// Non USE_DMA_SPEC does not support configurable ON/OFF of UART DMA
|
// Non USE_DMA_SPEC does not support configurable ON/OFF of UART DMA
|
||||||
|
|
||||||
if (hardware->rxDMAResource) {
|
if (hardware->rxDMAResource) {
|
||||||
|
@ -434,11 +527,11 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
uartPort->txDMAMuxId = hardware->txDMAMuxId;
|
uartPort->txDMAMuxId = hardware->txDMAMuxId;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* USE_DMA_SPEC */
|
||||||
|
|
||||||
if (uartPort->txDMAResource) {
|
if (uartPort->txDMAResource) {
|
||||||
dmaIdentifier_e identifier = dmaGetIdentifier(uartPort->txDMAResource);
|
const dmaIdentifier_e identifier = dmaGetIdentifier(uartPort->txDMAResource);
|
||||||
if (dmaAllocate(identifier, OWNER_SERIAL_TX, RESOURCE_INDEX(hardware->device))) {
|
if (dmaAllocate(identifier, ownerTxRx, ownerIndex)) {
|
||||||
dmaEnable(identifier);
|
dmaEnable(identifier);
|
||||||
#if defined(AT32F4)
|
#if defined(AT32F4)
|
||||||
dmaMuxEnable(identifier, uartPort->txDMAMuxId);
|
dmaMuxEnable(identifier, uartPort->txDMAMuxId);
|
||||||
|
@ -449,8 +542,8 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uartPort->rxDMAResource) {
|
if (uartPort->rxDMAResource) {
|
||||||
dmaIdentifier_e identifier = dmaGetIdentifier(uartPort->rxDMAResource);
|
const dmaIdentifier_e identifier = dmaGetIdentifier(uartPort->rxDMAResource);
|
||||||
if (dmaAllocate(identifier, OWNER_SERIAL_RX, RESOURCE_INDEX(hardware->device))) {
|
if (dmaAllocate(identifier, ownerTxRx + 1, ownerIndex)) {
|
||||||
dmaEnable(identifier);
|
dmaEnable(identifier);
|
||||||
#if defined(AT32F4)
|
#if defined(AT32F4)
|
||||||
dmaMuxEnable(identifier, uartPort->rxDMAMuxId);
|
dmaMuxEnable(identifier, uartPort->rxDMAMuxId);
|
||||||
|
@ -461,12 +554,13 @@ void uartConfigureDma(uartDevice_t *uartdev)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UART_IRQHandler(type, number, dev) \
|
#define UART_IRQHandler(type, number, dev) \
|
||||||
FAST_IRQ_HANDLER void type ## number ## _IRQHandler(void) \
|
FAST_IRQ_HANDLER void type ## number ## _IRQHandler(void) \
|
||||||
{ \
|
{ \
|
||||||
uartPort_t *uartPort = &(uartDevmap[dev]->port); \
|
uartPort_t *uartPort = &(uartDevice[(dev)].port); \
|
||||||
uartIrqHandler(uartPort); \
|
uartIrqHandler(uartPort); \
|
||||||
}
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
UART_IRQHandler(USART, 1, UARTDEV_1) // USART1 Rx/Tx IRQ Handler
|
UART_IRQHandler(USART, 1, UARTDEV_1) // USART1 Rx/Tx IRQ Handler
|
||||||
|
@ -509,7 +603,7 @@ UART_IRQHandler(UART, 10, UARTDEV_10) // UART10 Rx/Tx IRQ Handler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
UART_IRQHandler(LPUART, 1, LPUARTDEV_1) // LPUART1 Rx/Tx IRQ Handler
|
UART_IRQHandler(LPUART, 1, UARTDEV_LP1) // LPUART1 Rx/Tx IRQ Handler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,30 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "drivers/dma.h" // For dmaResource_t
|
#include "drivers/dma.h" // For dmaResource_t
|
||||||
|
#include "io/serial.h" // TODO: maybe move serialPortIdentifier_e into separate header
|
||||||
// Since serial ports can be used for any function these buffer sizes should be equal
|
|
||||||
// The two largest things that need to be sent are: 1, MSP responses, 2, UBLOX SVINFO packet.
|
|
||||||
|
|
||||||
// Size must be a power of two due to various optimizations which use 'and' instead of 'mod'
|
|
||||||
// Various serial routines return the buffer occupied size as uint8_t which would need to be extended in order to
|
|
||||||
// increase size further.
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
UARTDEV_1 = 0,
|
|
||||||
UARTDEV_2 = 1,
|
|
||||||
UARTDEV_3 = 2,
|
|
||||||
UARTDEV_4 = 3,
|
|
||||||
UARTDEV_5 = 4,
|
|
||||||
UARTDEV_6 = 5,
|
|
||||||
UARTDEV_7 = 6,
|
|
||||||
UARTDEV_8 = 7,
|
|
||||||
UARTDEV_9 = 8,
|
|
||||||
UARTDEV_10 = 9,
|
|
||||||
LPUARTDEV_1 = 10,
|
|
||||||
UARTDEV_COUNT
|
|
||||||
} UARTDevice_e;
|
|
||||||
|
|
||||||
STATIC_ASSERT(UARTDEV_COUNT == SERIAL_PORT_MAX_INDEX, serial_pinconfig_does_not_match_uartdevs);
|
|
||||||
|
|
||||||
typedef struct uartPort_s {
|
typedef struct uartPort_s {
|
||||||
serialPort_t port;
|
serialPort_t port;
|
||||||
|
@ -84,4 +61,4 @@ typedef struct uartPort_s {
|
||||||
} uartPort_t;
|
} uartPort_t;
|
||||||
|
|
||||||
void uartPinConfigure(const serialPinConfig_t *pSerialPinConfig);
|
void uartPinConfigure(const serialPinConfig_t *pSerialPinConfig);
|
||||||
serialPort_t *uartOpen(UARTDevice_e device, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options);
|
serialPort_t *uartOpen(serialPortIdentifier_e identifier, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options);
|
||||||
|
|
210
src/main/drivers/serial_uart_hw.c
Normal file
210
src/main/drivers/serial_uart_hw.c
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Betaflight.
|
||||||
|
*
|
||||||
|
* Betaflight is free software. You can redistribute this software
|
||||||
|
* and/or modify this software 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.
|
||||||
|
*
|
||||||
|
* Betaflight 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 this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common UART hardware functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#if defined(USE_UART) && !defined(SIMULATOR_BUILD)
|
||||||
|
|
||||||
|
#include "build/build_config.h"
|
||||||
|
|
||||||
|
#include "drivers/nvic.h"
|
||||||
|
#include "drivers/rcc.h"
|
||||||
|
#include "drivers/inverter.h"
|
||||||
|
#include "drivers/serial.h"
|
||||||
|
#include "drivers/serial_impl.h"
|
||||||
|
#include "drivers/serial_uart.h"
|
||||||
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
|
// TODO: split this function into mcu-specific UART files ?
|
||||||
|
static void enableRxIrq(const uartHardware_t *hardware)
|
||||||
|
{
|
||||||
|
#if defined(USE_HAL_DRIVER)
|
||||||
|
HAL_NVIC_SetPriority(hardware->irqn, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
||||||
|
HAL_NVIC_EnableIRQ(hardware->irqn);
|
||||||
|
#elif defined(STM32F4)
|
||||||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannel = hardware->irqn;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(hardware->rxPriority);
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(hardware->rxPriority);
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||||
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
#elif defined(AT32F4)
|
||||||
|
nvic_irq_enable(hardware->irqn, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
||||||
|
#elif defined(APM32F4)
|
||||||
|
DAL_NVIC_SetPriority(hardware->irqn, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
||||||
|
DAL_NVIC_EnableIRQ(hardware->irqn);
|
||||||
|
#else
|
||||||
|
# error "Unhandled MCU type"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uartPort_t *serialUART(uartDevice_t *uartdev, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
||||||
|
{
|
||||||
|
uartPort_t *s = &uartdev->port;
|
||||||
|
|
||||||
|
const uartHardware_t *hardware = uartdev->hardware;
|
||||||
|
|
||||||
|
s->port.vTable = uartVTable;
|
||||||
|
|
||||||
|
s->port.baudRate = baudRate;
|
||||||
|
|
||||||
|
s->port.rxBuffer = hardware->rxBuffer;
|
||||||
|
s->port.txBuffer = hardware->txBuffer;
|
||||||
|
s->port.rxBufferSize = hardware->rxBufferSize;
|
||||||
|
s->port.txBufferSize = hardware->txBufferSize;
|
||||||
|
|
||||||
|
s->USARTx = hardware->reg;
|
||||||
|
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
s->Handle.Instance = hardware->reg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s->checkUsartTxOutput = checkUsartTxOutput;
|
||||||
|
|
||||||
|
if (hardware->rcc) {
|
||||||
|
RCC_ClockCmd(hardware->rcc, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
|
uartConfigureDma(uartdev);
|
||||||
|
s->txDMAEmpty = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
||||||
|
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
||||||
|
|
||||||
|
uartdev->txPinState = TX_PIN_IGNORE;
|
||||||
|
|
||||||
|
const serialPortIdentifier_e identifier = s->port.identifier;
|
||||||
|
|
||||||
|
const int ownerIndex = serialOwnerIndex(identifier);
|
||||||
|
const resourceOwner_e ownerTxRx = serialOwnerTxRx(identifier); // rx is always +1
|
||||||
|
|
||||||
|
// prepare AF modes
|
||||||
|
#if UART_TRAIT_AF_PORT
|
||||||
|
uint8_t rxAf = hardware->af;
|
||||||
|
uint8_t txAf = hardware->af;
|
||||||
|
#elif UART_TRAIT_AF_PIN
|
||||||
|
uint8_t rxAf = uartdev->rx.af;
|
||||||
|
uint8_t txAf = uartdev->tx.af;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Note: F4 did not check txIO before refactoring
|
||||||
|
if ((options & SERIAL_BIDIR) && txIO) {
|
||||||
|
// pushPull / openDrain
|
||||||
|
const bool pushPull = serialOptions_pushPull(options);
|
||||||
|
// pull direction
|
||||||
|
const serialPullMode_t pull = serialOptions_pull(options);
|
||||||
|
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
||||||
|
// Note: APM32F4 is different from STM32F4 here
|
||||||
|
const ioConfig_t ioCfg = IO_CONFIG(
|
||||||
|
pushPull ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
|
||||||
|
GPIO_SPEED_FREQ_HIGH,
|
||||||
|
((const unsigned[]){GPIO_NOPULL, GPIO_PULLDOWN, GPIO_PULLUP})[pull]
|
||||||
|
);
|
||||||
|
#elif defined(AT32F4)
|
||||||
|
const ioConfig_t ioCfg = IO_CONFIG(
|
||||||
|
GPIO_MODE_MUX,
|
||||||
|
GPIO_DRIVE_STRENGTH_STRONGER,
|
||||||
|
pushPull ? GPIO_OUTPUT_PUSH_PULL : GPIO_OUTPUT_OPEN_DRAIN,
|
||||||
|
((const gpio_pull_type[]){GPIO_PULL_NONE, GPIO_PULL_DOWN, GPIO_PULL_UP})[pull]
|
||||||
|
);
|
||||||
|
#elif defined(STM32F4)
|
||||||
|
// UART inverter is not supproted on F4, but keep it in line with other CPUs
|
||||||
|
// External inverter in bidir mode would be quite problematic anyway
|
||||||
|
const ioConfig_t ioCfg = IO_CONFIG(
|
||||||
|
GPIO_Mode_AF,
|
||||||
|
GPIO_Low_Speed, // TODO: should use stronger drive
|
||||||
|
pushPull ? GPIO_OType_PP : GPIO_OType_OD,
|
||||||
|
((const unsigned[]){GPIO_PuPd_NOPULL, GPIO_PuPd_DOWN, GPIO_PuPd_UP})[pull]
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
IOInit(txIO, ownerTxRx, ownerIndex);
|
||||||
|
IOConfigGPIOAF(txIO, ioCfg, txAf);
|
||||||
|
} else {
|
||||||
|
if ((mode & MODE_TX) && txIO) {
|
||||||
|
IOInit(txIO, ownerTxRx, ownerIndex);
|
||||||
|
|
||||||
|
if (options & SERIAL_CHECK_TX) {
|
||||||
|
#if defined(STM32F7)
|
||||||
|
// see https://github.com/betaflight/betaflight/pull/13021
|
||||||
|
// Allow for F7 UART idle preamble to be sent on startup
|
||||||
|
uartdev->txPinState = TX_PIN_MONITOR;
|
||||||
|
// Switch TX to UART output whilst UART sends idle preamble
|
||||||
|
checkUsartTxOutput(s);
|
||||||
|
#else
|
||||||
|
uartdev->txPinState = TX_PIN_ACTIVE;
|
||||||
|
// Switch TX to an input with pullup so it's state can be monitored
|
||||||
|
uartTxMonitor(s);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if defined(STM32F4) || defined(APM32F4)
|
||||||
|
// TODO: no need for pullup on TX only pin
|
||||||
|
const ioConfig_t ioCfg = IOCFG_AF_PP_UP;
|
||||||
|
#else
|
||||||
|
const ioConfig_t ioCfg = IOCFG_AF_PP;
|
||||||
|
#endif
|
||||||
|
IOConfigGPIOAF(txIO, ioCfg, txAf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mode & MODE_RX) && rxIO) {
|
||||||
|
#if defined(STM32F4) || defined(APM32F4)
|
||||||
|
// no inversion possible on F4, always use pullup
|
||||||
|
const ioConfig_t ioCfg = IOCFG_AF_PP_UP;
|
||||||
|
#else
|
||||||
|
// TODO: pullup/pulldown should be enabled for RX (based on inversion)
|
||||||
|
const ioConfig_t ioCfg = IOCFG_AF_PP;
|
||||||
|
#endif
|
||||||
|
IOInit(rxIO, ownerTxRx + 1, ownerIndex);
|
||||||
|
IOConfigGPIOAF(rxIO, ioCfg, rxAf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true
|
||||||
|
#ifdef USE_DMA
|
||||||
|
&& !s->rxDMAResource // do not enable IRW if using rxDMA
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
enableRxIrq(hardware);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called from platform-specific uartReconfigure
|
||||||
|
void uartConfigureExternalPinInversion(uartPort_t *uartPort)
|
||||||
|
{
|
||||||
|
#if !defined(USE_INVERTER)
|
||||||
|
UNUSED(uartPort);
|
||||||
|
#else
|
||||||
|
const bool inverted = uartPort->port.options & SERIAL_INVERTED;
|
||||||
|
enableInverter(uartPort->port.identifier, inverted);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_UART */
|
|
@ -22,8 +22,28 @@
|
||||||
|
|
||||||
// Configuration constants
|
// Configuration constants
|
||||||
|
|
||||||
|
// TODO: this comment is obsolete
|
||||||
|
|
||||||
|
// Since serial ports can be used for any function these buffer sizes should be equal
|
||||||
|
// The two largest things that need to be sent are: 1, MSP responses, 2, UBLOX SVINFO packet.
|
||||||
|
|
||||||
|
// Size must be a power of two due to various optimizations which use 'and' instead of 'mod'
|
||||||
|
// Various serial routines return the buffer occupied size as uint8_t which would need to be extended in order to
|
||||||
|
// increase size further.
|
||||||
|
|
||||||
|
// define some common UART features
|
||||||
|
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(AT32F43x)
|
||||||
|
#define UART_TRAIT_AF_PIN 1 // pin AF mode is configured for each pin individually
|
||||||
|
#else
|
||||||
|
#define UART_TRAIT_AF_PORT 1 // all pins on given uart use same AF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(STM32F4) || !defined(APM32F4) // all others support pinswap
|
||||||
|
#define UART_TRAIT_PINSWAP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(STM32F4)
|
#if defined(STM32F4)
|
||||||
#define UARTDEV_COUNT_MAX 6
|
|
||||||
#define UARTHARDWARE_MAX_PINS 4
|
#define UARTHARDWARE_MAX_PINS 4
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -35,8 +55,9 @@
|
||||||
#define UART_TX_BUFFER_SIZE 256
|
#define UART_TX_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(STM32F7)
|
#elif defined(STM32F7)
|
||||||
#define UARTDEV_COUNT_MAX 8
|
|
||||||
#define UARTHARDWARE_MAX_PINS 4
|
#define UARTHARDWARE_MAX_PINS 4
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -48,8 +69,9 @@
|
||||||
#define UART_TX_BUFFER_SIZE 256
|
#define UART_TX_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(STM32H7)
|
#elif defined(STM32H7)
|
||||||
#define UARTDEV_COUNT_MAX 11 // UARTs 1 to 10 + LPUART1
|
|
||||||
#define UARTHARDWARE_MAX_PINS 5
|
#define UARTHARDWARE_MAX_PINS 5
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -61,8 +83,9 @@
|
||||||
#define UART_TX_BUFFER_SIZE 256
|
#define UART_TX_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(STM32G4)
|
#elif defined(STM32G4)
|
||||||
#define UARTDEV_COUNT_MAX 11 // UARTs 1 to 5 + LPUART1 (index 10)
|
|
||||||
#define UARTHARDWARE_MAX_PINS 3
|
#define UARTHARDWARE_MAX_PINS 3
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -74,8 +97,9 @@
|
||||||
#define UART_TX_BUFFER_SIZE 256
|
#define UART_TX_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(AT32F4)
|
#elif defined(AT32F4)
|
||||||
#define UARTDEV_COUNT_MAX 8 // UARTs 1 to 5 + LPUART1 (index 9)
|
|
||||||
#define UARTHARDWARE_MAX_PINS 5
|
#define UARTHARDWARE_MAX_PINS 5
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -88,7 +112,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#elif defined(APM32F4)
|
#elif defined(APM32F4)
|
||||||
#define UARTDEV_COUNT_MAX 6
|
|
||||||
#define UARTHARDWARE_MAX_PINS 4
|
#define UARTHARDWARE_MAX_PINS 4
|
||||||
#ifndef UART_RX_BUFFER_SIZE
|
#ifndef UART_RX_BUFFER_SIZE
|
||||||
#define UART_RX_BUFFER_SIZE 256
|
#define UART_RX_BUFFER_SIZE 256
|
||||||
|
@ -100,89 +124,59 @@
|
||||||
#define UART_TX_BUFFER_SIZE 256
|
#define UART_TX_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error unknown MCU family
|
#error unknown MCU family
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Count number of configured UARTs
|
// compressed index of UART/LPUART. Direct index into uartDevice[]
|
||||||
|
typedef enum {
|
||||||
|
UARTDEV_INVALID = -1,
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
#define UARTDEV_COUNT_1 1
|
UARTDEV_1,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_1 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
#define UARTDEV_COUNT_2 1
|
UARTDEV_2,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_2 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
#define UARTDEV_COUNT_3 1
|
UARTDEV_3,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_3 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
#define UARTDEV_COUNT_4 1
|
UARTDEV_4,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_4 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
#define UARTDEV_COUNT_5 1
|
UARTDEV_5,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_5 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
#define UARTDEV_COUNT_6 1
|
UARTDEV_6,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_6 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART7
|
#ifdef USE_UART7
|
||||||
#define UARTDEV_COUNT_7 1
|
UARTDEV_7,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_7 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART8
|
#ifdef USE_UART8
|
||||||
#define UARTDEV_COUNT_8 1
|
UARTDEV_8,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_8 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART9
|
#ifdef USE_UART9
|
||||||
#define UARTDEV_COUNT_9 1
|
UARTDEV_9,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_9 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART10
|
#ifdef USE_UART10
|
||||||
#define UARTDEV_COUNT_10 1
|
UARTDEV_10,
|
||||||
#else
|
|
||||||
#define UARTDEV_COUNT_10 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
#define LPUARTDEV_COUNT_1 1
|
UARTDEV_LP1,
|
||||||
#else
|
|
||||||
#define LPUARTDEV_COUNT_1 0
|
|
||||||
#endif
|
#endif
|
||||||
|
UARTDEV_COUNT
|
||||||
#define UARTDEV_COUNT (UARTDEV_COUNT_1 + UARTDEV_COUNT_2 + UARTDEV_COUNT_3 + UARTDEV_COUNT_4 + UARTDEV_COUNT_5 + UARTDEV_COUNT_6 + UARTDEV_COUNT_7 + UARTDEV_COUNT_8 + UARTDEV_COUNT_9 + UARTDEV_COUNT_10 + LPUARTDEV_COUNT_1)
|
} uartDeviceIdx_e;
|
||||||
|
|
||||||
typedef struct uartPinDef_s {
|
typedef struct uartPinDef_s {
|
||||||
ioTag_t pin;
|
ioTag_t pin;
|
||||||
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(AT32F43x) || defined(APM32F4)
|
#if UART_TRAIT_AF_PIN
|
||||||
uint8_t af;
|
uint8_t af;
|
||||||
#endif
|
#endif
|
||||||
} uartPinDef_t;
|
} uartPinDef_t;
|
||||||
|
|
||||||
typedef struct uartHardware_s {
|
typedef struct uartHardware_s {
|
||||||
UARTDevice_e device; // XXX Not required for full allocation
|
serialPortIdentifier_e identifier;
|
||||||
USART_TypeDef* reg;
|
USART_TypeDef* reg;
|
||||||
|
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
|
@ -190,14 +184,14 @@ typedef struct uartHardware_s {
|
||||||
dmaResource_t *rxDMAResource;
|
dmaResource_t *rxDMAResource;
|
||||||
// For H7 and G4 , {tx|rx}DMAChannel are DMAMUX input index for peripherals (DMA_REQUEST_xxx); H7:RM0433 Table 110, G4:RM0440 Table 80.
|
// For H7 and G4 , {tx|rx}DMAChannel are DMAMUX input index for peripherals (DMA_REQUEST_xxx); H7:RM0433 Table 110, G4:RM0440 Table 80.
|
||||||
// For F4 and F7, these are 32-bit channel identifiers (DMA_CHANNEL_x)
|
// For F4 and F7, these are 32-bit channel identifiers (DMA_CHANNEL_x)
|
||||||
// For at32f435/7 DmaChannel is the dmamux ,need to call dmamuxenable using dmamuxid
|
// For at32f435/7 DmaChannel is the dmamux, need to call dmamuxenable using dmamuxid
|
||||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) || defined(APM32F4)
|
||||||
uint32_t txDMAChannel;
|
uint32_t txDMAChannel;
|
||||||
uint32_t rxDMAChannel;
|
uint32_t rxDMAChannel;
|
||||||
#elif defined(AT32F4)
|
#elif defined(AT32F4)
|
||||||
uint32_t txDMAMuxId;//for dmaspec->dmamux and using dmaMuxEnable(dmax,muxid)
|
uint32_t txDMAMuxId;//for dmaspec->dmamux and using dmaMuxEnable(dmax,muxid)
|
||||||
uint32_t rxDMAMuxId;
|
uint32_t rxDMAMuxId;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // USE_DMA
|
#endif // USE_DMA
|
||||||
|
|
||||||
|
@ -206,16 +200,12 @@ typedef struct uartHardware_s {
|
||||||
|
|
||||||
rccPeriphTag_t rcc;
|
rccPeriphTag_t rcc;
|
||||||
|
|
||||||
#if !defined(STM32F7)
|
#if UART_TRAIT_AF_PORT
|
||||||
uint8_t af;
|
uint8_t af;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
|
uint8_t irqn; // uart IRQ. One shared IRQ per uart
|
||||||
uint8_t txIrq;
|
|
||||||
uint8_t rxIrq;
|
|
||||||
#else
|
|
||||||
uint8_t irqn;
|
|
||||||
#endif
|
|
||||||
uint8_t txPriority;
|
uint8_t txPriority;
|
||||||
uint8_t rxPriority;
|
uint8_t rxPriority;
|
||||||
|
|
||||||
|
@ -225,7 +215,7 @@ typedef struct uartHardware_s {
|
||||||
uint16_t rxBufferSize;
|
uint16_t rxBufferSize;
|
||||||
} uartHardware_t;
|
} uartHardware_t;
|
||||||
|
|
||||||
extern const uartHardware_t uartHardware[];
|
extern const uartHardware_t uartHardware[UARTDEV_COUNT];
|
||||||
|
|
||||||
// uartDevice_t is an actual device instance.
|
// uartDevice_t is an actual device instance.
|
||||||
// XXX Instances are allocated for uarts defined by USE_UARTx atm.
|
// XXX Instances are allocated for uarts defined by USE_UARTx atm.
|
||||||
|
@ -236,6 +226,7 @@ typedef enum {
|
||||||
TX_PIN_IGNORE
|
TX_PIN_IGNORE
|
||||||
} txPinState_t;
|
} txPinState_t;
|
||||||
|
|
||||||
|
// TODO: merge uartPort_t and uartDevice_t
|
||||||
typedef struct uartDevice_s {
|
typedef struct uartDevice_s {
|
||||||
uartPort_t port;
|
uartPort_t port;
|
||||||
const uartHardware_t *hardware;
|
const uartHardware_t *hardware;
|
||||||
|
@ -243,19 +234,24 @@ typedef struct uartDevice_s {
|
||||||
uartPinDef_t tx;
|
uartPinDef_t tx;
|
||||||
volatile uint8_t *rxBuffer;
|
volatile uint8_t *rxBuffer;
|
||||||
volatile uint8_t *txBuffer;
|
volatile uint8_t *txBuffer;
|
||||||
#if !defined(STM32F4) || !defined(APM32F4) // Don't support pin swap.
|
#if UART_TRAIT_PINSWAP
|
||||||
bool pinSwap;
|
bool pinSwap;
|
||||||
#endif
|
#endif
|
||||||
txPinState_t txPinState;
|
txPinState_t txPinState;
|
||||||
} uartDevice_t;
|
} uartDevice_t;
|
||||||
|
|
||||||
extern uartDevice_t *uartDevmap[];
|
extern uartDevice_t uartDevice[UARTDEV_COUNT]; // indexed by uartDeviceIdx_e;
|
||||||
|
|
||||||
|
uartDeviceIdx_e uartDeviceIdxFromIdentifier(serialPortIdentifier_e identifier);
|
||||||
|
uartDevice_t* uartDeviceFromIdentifier(serialPortIdentifier_e identifier);
|
||||||
|
|
||||||
extern const struct serialPortVTable uartVTable[];
|
extern const struct serialPortVTable uartVTable[];
|
||||||
|
|
||||||
void uartTryStartTxDMA(uartPort_t *s);
|
void uartTryStartTxDMA(uartPort_t *s);
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options);
|
uartPort_t *serialUART(uartDevice_t *uart, uint32_t baudRate, portMode_e mode, portOptions_e options);
|
||||||
|
|
||||||
|
void uartConfigureExternalPinInversion(uartPort_t *uartPort);
|
||||||
|
|
||||||
void uartIrqHandler(uartPort_t *s);
|
void uartIrqHandler(uartPort_t *s);
|
||||||
|
|
||||||
|
@ -284,15 +280,10 @@ void uartTxMonitor(uartPort_t *s);
|
||||||
|
|
||||||
#define UART_BUFFER(type, n, rxtx) type volatile uint8_t uart ## n ## rxtx ## xBuffer[UART_ ## rxtx ## X_BUFFER_SIZE]
|
#define UART_BUFFER(type, n, rxtx) type volatile uint8_t uart ## n ## rxtx ## xBuffer[UART_ ## rxtx ## X_BUFFER_SIZE]
|
||||||
|
|
||||||
#define UART_BUFFERS_EXTERN(n) \
|
#define UART_BUFFERS_EXTERN(n) \
|
||||||
UART_BUFFER(extern, n, R); \
|
UART_BUFFER(extern, n, R); \
|
||||||
UART_BUFFER(extern, n, T); struct dummy_s
|
UART_BUFFER(extern, n, T); struct dummy_s \
|
||||||
|
/**/
|
||||||
#define LPUART_BUFFER(type, n, rxtx) type volatile uint8_t lpuart ## n ## rxtx ## xBuffer[UART_ ## rxtx ## X_BUFFER_SIZE]
|
|
||||||
|
|
||||||
#define LPUART_BUFFERS_EXTERN(n) \
|
|
||||||
LPUART_BUFFER(extern, n, R); \
|
|
||||||
LPUART_BUFFER(extern, n, T); struct dummy_s
|
|
||||||
|
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
UART_BUFFERS_EXTERN(1);
|
UART_BUFFERS_EXTERN(1);
|
||||||
|
@ -335,7 +326,7 @@ UART_BUFFERS_EXTERN(10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
LPUART_BUFFERS_EXTERN(1);
|
UART_BUFFERS_EXTERN(Lp1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef UART_BUFFERS_EXTERN
|
#undef UART_BUFFERS_EXTERN
|
||||||
|
|
|
@ -41,48 +41,47 @@
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
static FAST_DATA_ZERO_INIT uartDevice_t uartDevice[UARTDEV_COUNT]; // Only those configured in target.h
|
|
||||||
FAST_DATA_ZERO_INIT uartDevice_t *uartDevmap[UARTDEV_COUNT_MAX]; // Full array
|
|
||||||
|
|
||||||
void uartPinConfigure(const serialPinConfig_t *pSerialPinConfig)
|
void uartPinConfigure(const serialPinConfig_t *pSerialPinConfig)
|
||||||
{
|
{
|
||||||
uartDevice_t *uartdev = uartDevice;
|
for (const uartHardware_t* hardware = uartHardware; hardware < ARRAYEND(uartHardware); hardware++) {
|
||||||
|
const serialPortIdentifier_e identifier = hardware->identifier;
|
||||||
for (size_t hindex = 0; hindex < UARTDEV_COUNT; hindex++) {
|
uartDevice_t* uartdev = uartDeviceFromIdentifier(identifier);
|
||||||
|
const int resourceIndex = serialResourceIndex(identifier);
|
||||||
const uartHardware_t *hardware = &uartHardware[hindex];
|
if (uartdev == NULL || resourceIndex < 0) {
|
||||||
const UARTDevice_e device = hardware->device;
|
// malformed uartHardware
|
||||||
|
continue;
|
||||||
#if !defined(STM32F4) || !defined(APM32F4) // Don't support pin swap.
|
}
|
||||||
uartdev->pinSwap = false;
|
const ioTag_t cfgRx = pSerialPinConfig->ioTagRx[resourceIndex];
|
||||||
|
const ioTag_t cfgTx = pSerialPinConfig->ioTagTx[resourceIndex];
|
||||||
|
#if UART_TRAIT_PINSWAP
|
||||||
|
bool swap = false;
|
||||||
#endif
|
#endif
|
||||||
for (int pindex = 0 ; pindex < UARTHARDWARE_MAX_PINS ; pindex++) {
|
for (unsigned pindex = 0 ; pindex < UARTHARDWARE_MAX_PINS ; pindex++) {
|
||||||
if (pSerialPinConfig->ioTagRx[device] && (pSerialPinConfig->ioTagRx[device] == hardware->rxPins[pindex].pin)) {
|
if (cfgRx && cfgRx == hardware->rxPins[pindex].pin) {
|
||||||
uartdev->rx = hardware->rxPins[pindex];
|
uartdev->rx = hardware->rxPins[pindex];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSerialPinConfig->ioTagTx[device] && (pSerialPinConfig->ioTagTx[device] == hardware->txPins[pindex].pin)) {
|
if (cfgTx && cfgTx == hardware->txPins[pindex].pin) {
|
||||||
uartdev->tx = hardware->txPins[pindex];
|
uartdev->tx = hardware->txPins[pindex];
|
||||||
}
|
}
|
||||||
|
#if UART_TRAIT_PINSWAP
|
||||||
|
|
||||||
#if !defined(STM32F4) || !defined(APM32F4)
|
|
||||||
// Check for swapped pins
|
// Check for swapped pins
|
||||||
if (pSerialPinConfig->ioTagTx[device] && (pSerialPinConfig->ioTagTx[device] == hardware->rxPins[pindex].pin)) {
|
if (cfgTx && cfgTx == hardware->rxPins[pindex].pin) {
|
||||||
uartdev->tx = hardware->rxPins[pindex];
|
uartdev->tx = hardware->rxPins[pindex];
|
||||||
uartdev->pinSwap = true;
|
swap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSerialPinConfig->ioTagRx[device] && (pSerialPinConfig->ioTagRx[device] == hardware->txPins[pindex].pin)) {
|
if (cfgRx && cfgRx == hardware->txPins[pindex].pin) {
|
||||||
uartdev->rx = hardware->txPins[pindex];
|
uartdev->rx = hardware->txPins[pindex];
|
||||||
uartdev->pinSwap = true;
|
swap = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (uartdev->rx.pin || uartdev->tx.pin ) {
|
||||||
if (uartdev->rx.pin || uartdev->tx.pin) {
|
|
||||||
uartdev->hardware = hardware;
|
uartdev->hardware = hardware;
|
||||||
uartDevmap[device] = uartdev++;
|
#if UART_TRAIT_PINSWAP
|
||||||
|
uartdev->pinSwap = swap;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ static void sdCardAndFSInit(void)
|
||||||
|
|
||||||
void init(void)
|
void init(void)
|
||||||
{
|
{
|
||||||
#ifdef SERIAL_PORT_COUNT
|
#if SERIAL_PORT_COUNT > 0
|
||||||
printfSerialInit();
|
printfSerialInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -519,17 +519,21 @@ void init(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(AVOID_UART1_FOR_PWM_PPM)
|
#if defined(AVOID_UART1_FOR_PWM_PPM)
|
||||||
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL),
|
# define SERIALPORT_TO_AVOID SERIAL_PORT_USART1
|
||||||
featureIsEnabled(FEATURE_RX_PPM) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART1 : SERIAL_PORT_NONE);
|
|
||||||
#elif defined(AVOID_UART2_FOR_PWM_PPM)
|
#elif defined(AVOID_UART2_FOR_PWM_PPM)
|
||||||
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL),
|
# define SERIALPORT_TO_AVOID SERIAL_PORT_USART2
|
||||||
featureIsEnabled(FEATURE_RX_PPM) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART2 : SERIAL_PORT_NONE);
|
|
||||||
#elif defined(AVOID_UART3_FOR_PWM_PPM)
|
#elif defined(AVOID_UART3_FOR_PWM_PPM)
|
||||||
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL),
|
# define SERIALPORT_TO_AVOID SERIAL_PORT_USART3
|
||||||
featureIsEnabled(FEATURE_RX_PPM) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART3 : SERIAL_PORT_NONE);
|
|
||||||
#else
|
|
||||||
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL), SERIAL_PORT_NONE);
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
serialPortIdentifier_e serialPortToAvoid = SERIAL_PORT_NONE;
|
||||||
|
#if defined(SERIALPORT_TO_AVOID)
|
||||||
|
if (featureIsEnabled(FEATURE_RX_PPM) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM)) {
|
||||||
|
serialPortToAvoid = SERIALPORT_TO_AVOID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL), serialPortToAvoid);
|
||||||
|
}
|
||||||
|
|
||||||
mixerInit(mixerConfig()->mixerMode);
|
mixerInit(mixerConfig()->mixerMode);
|
||||||
|
|
||||||
|
|
|
@ -435,8 +435,8 @@ void gpsInit(void)
|
||||||
mode &= ~MODE_TX;
|
mode &= ~MODE_TX;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (serialType(gpsPortConfig->identifier) == SERIALTYPE_UART
|
||||||
if ((gpsPortConfig->identifier >= SERIAL_PORT_USART1) && (gpsPortConfig->identifier <= SERIAL_PORT_USART_MAX)){
|
|| serialType(gpsPortConfig->identifier) == SERIALTYPE_LPUART){
|
||||||
options |= SERIAL_CHECK_TX;
|
options |= SERIAL_CHECK_TX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,10 @@ const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
|
||||||
#ifdef USE_UART10
|
#ifdef USE_UART10
|
||||||
SERIAL_PORT_USART10,
|
SERIAL_PORT_USART10,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SOFTSERIAL
|
#ifdef USE_SOFTSERIAL1
|
||||||
SERIAL_PORT_SOFTSERIAL1,
|
SERIAL_PORT_SOFTSERIAL1,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL2
|
||||||
SERIAL_PORT_SOFTSERIAL2,
|
SERIAL_PORT_SOFTSERIAL2,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
|
@ -109,24 +111,77 @@ const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* serialPortNames[SERIAL_PORT_COUNT] = {
|
||||||
|
#ifdef USE_VCP
|
||||||
|
"VCP",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART1
|
||||||
|
"UART1",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
|
"UART2",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
|
"UART3",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
|
"UART4",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
|
"UART5",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
|
"UART6",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART7
|
||||||
|
"UART7",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART8
|
||||||
|
"UART8",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART9
|
||||||
|
"UART9",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART10
|
||||||
|
"UART10",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL1
|
||||||
|
"SOFT1",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL2
|
||||||
|
"SOFT2",
|
||||||
|
#endif
|
||||||
|
#ifdef USE_LPUART1
|
||||||
|
"LPUART1",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
static uint8_t serialPortCount;
|
static uint8_t serialPortCount;
|
||||||
|
|
||||||
const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000,
|
const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000,
|
||||||
400000, 460800, 500000, 921600, 1000000, 1500000, 2000000, 2470000}; // see baudRate_e
|
400000, 460800, 500000, 921600, 1000000, 1500000, 2000000, 2470000}; // see baudRate_e
|
||||||
|
|
||||||
#define BAUD_RATE_COUNT ARRAYLEN(baudRates)
|
static serialPortConfig_t* findInPortConfigs_identifier(const serialPortConfig_t cfgs[], size_t count, serialPortIdentifier_e identifier)
|
||||||
|
|
||||||
serialPortConfig_t *serialFindPortConfigurationMutable(serialPortIdentifier_e identifier)
|
|
||||||
{
|
{
|
||||||
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
for (unsigned i = 0; i < count; i++) {
|
||||||
serialPortConfig_t *candidate = &serialConfigMutable()->portConfigs[index];
|
if (cfgs[i].identifier == identifier) {
|
||||||
if (candidate->identifier == identifier) {
|
// drop const on return - wrapper function will add it back if necessary
|
||||||
return candidate;
|
return (serialPortConfig_t*)&cfgs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serialPortConfig_t* serialFindPortConfigurationMutable(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
return findInPortConfigs_identifier(serialConfigMutable()->portConfigs, ARRAYLEN(serialConfigMutable()->portConfigs), identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
const serialPortConfig_t* serialFindPortConfiguration(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
return findInPortConfigs_identifier(serialConfigMutable()->portConfigs, ARRAYLEN(serialConfig()->portConfigs), identifier);
|
||||||
|
}
|
||||||
|
|
||||||
PG_REGISTER_WITH_RESET_FN(serialConfig_t, serialConfig, PG_SERIAL_CONFIG, 1);
|
PG_REGISTER_WITH_RESET_FN(serialConfig_t, serialConfig, PG_SERIAL_CONFIG, 1);
|
||||||
|
|
||||||
void pgResetFn_serialConfig(serialConfig_t *serialConfig)
|
void pgResetFn_serialConfig(serialConfig_t *serialConfig)
|
||||||
|
@ -134,11 +189,12 @@ void pgResetFn_serialConfig(serialConfig_t *serialConfig)
|
||||||
memset(serialConfig, 0, sizeof(serialConfig_t));
|
memset(serialConfig, 0, sizeof(serialConfig_t));
|
||||||
|
|
||||||
for (int i = 0; i < SERIAL_PORT_COUNT; i++) {
|
for (int i = 0; i < SERIAL_PORT_COUNT; i++) {
|
||||||
serialConfig->portConfigs[i].identifier = serialPortIdentifiers[i];
|
serialPortConfig_t* pCfg = &serialConfig->portConfigs[i];
|
||||||
serialConfig->portConfigs[i].msp_baudrateIndex = BAUD_115200;
|
pCfg->identifier = serialPortIdentifiers[i];
|
||||||
serialConfig->portConfigs[i].gps_baudrateIndex = BAUD_57600;
|
pCfg->msp_baudrateIndex = BAUD_115200;
|
||||||
serialConfig->portConfigs[i].telemetry_baudrateIndex = BAUD_AUTO;
|
pCfg->gps_baudrateIndex = BAUD_57600;
|
||||||
serialConfig->portConfigs[i].blackbox_baudrateIndex = BAUD_115200;
|
pCfg->telemetry_baudrateIndex = BAUD_AUTO;
|
||||||
|
pCfg->blackbox_baudrateIndex = BAUD_115200;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialConfig->portConfigs[0].functionMask = FUNCTION_MSP;
|
serialConfig->portConfigs[0].functionMask = FUNCTION_MSP;
|
||||||
|
@ -221,9 +277,7 @@ void pgResetFn_serialConfig(serialConfig_t *serialConfig)
|
||||||
|
|
||||||
baudRate_e lookupBaudRateIndex(uint32_t baudRate)
|
baudRate_e lookupBaudRateIndex(uint32_t baudRate)
|
||||||
{
|
{
|
||||||
uint8_t index;
|
for (unsigned index = 0; index < ARRAYLEN(baudRates); index++) {
|
||||||
|
|
||||||
for (index = 0; index < BAUD_RATE_COUNT; index++) {
|
|
||||||
if (baudRates[index] == baudRate) {
|
if (baudRates[index] == baudRate) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +287,7 @@ baudRate_e lookupBaudRateIndex(uint32_t baudRate)
|
||||||
|
|
||||||
int findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier)
|
int findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
for (unsigned index = 0; index < ARRAYLEN(serialPortIdentifiers); index++) {
|
||||||
if (serialPortIdentifiers[index] == identifier) {
|
if (serialPortIdentifiers[index] == identifier) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -241,13 +295,35 @@ int findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find serial port by name.
|
||||||
|
// when cmp is NULL, case-insensitive compare is used
|
||||||
|
// cmp is strcmp-like function
|
||||||
|
serialPortIdentifier_e findSerialPortByName(const char* portName, int (*cmp)(const char *portName, const char *candidate))
|
||||||
|
{
|
||||||
|
if (!cmp) { // use strcasecmp by default
|
||||||
|
cmp = strcasecmp;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < ARRAYLEN(serialPortNames); i++) {
|
||||||
|
if (cmp(portName, serialPortNames[i]) == 0) {
|
||||||
|
return serialPortIdentifiers[i]; // 1:1 map between names and identifiers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SERIAL_PORT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* serialName(serialPortIdentifier_e identifier, const char* notFound)
|
||||||
|
{
|
||||||
|
const int idx = findSerialPortIndexByIdentifier(identifier);
|
||||||
|
return idx >= 0 ? serialPortNames[idx] : notFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier)
|
serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
uint8_t index;
|
for (serialPortUsage_t* usage = serialPortUsageList; usage < ARRAYEND(serialPortUsageList); usage++) {
|
||||||
for (index = 0; index < SERIAL_PORT_COUNT; index++) {
|
if (usage->identifier == identifier) {
|
||||||
serialPortUsage_t *candidate = &serialPortUsageList[index];
|
return usage;
|
||||||
if (candidate->identifier == identifier) {
|
|
||||||
return candidate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -255,11 +331,9 @@ serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identi
|
||||||
|
|
||||||
serialPortUsage_t *findSerialPortUsageByPort(const serialPort_t *serialPort)
|
serialPortUsage_t *findSerialPortUsageByPort(const serialPort_t *serialPort)
|
||||||
{
|
{
|
||||||
uint8_t index;
|
for (serialPortUsage_t* usage = serialPortUsageList; usage < ARRAYEND(serialPortUsageList); usage++) {
|
||||||
for (index = 0; index < SERIAL_PORT_COUNT; index++) {
|
if (usage->serialPort == serialPort) {
|
||||||
serialPortUsage_t *candidate = &serialPortUsageList[index];
|
return usage;
|
||||||
if (candidate->serialPort == serialPort) {
|
|
||||||
return candidate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -280,7 +354,7 @@ const serialPortConfig_t *findSerialPortConfig(serialPortFunction_e function)
|
||||||
|
|
||||||
const serialPortConfig_t *findNextSerialPortConfig(serialPortFunction_e function)
|
const serialPortConfig_t *findNextSerialPortConfig(serialPortFunction_e function)
|
||||||
{
|
{
|
||||||
while (findSerialPortConfigState.lastIndex < SERIAL_PORT_COUNT) {
|
while (findSerialPortConfigState.lastIndex < ARRAYLEN(serialConfig()->portConfigs)) {
|
||||||
const serialPortConfig_t *candidate = &serialConfig()->portConfigs[findSerialPortConfigState.lastIndex++];
|
const serialPortConfig_t *candidate = &serialConfig()->portConfigs[findSerialPortConfigState.lastIndex++];
|
||||||
|
|
||||||
if (candidate->functionMask & function) {
|
if (candidate->functionMask & function) {
|
||||||
|
@ -305,7 +379,7 @@ bool isSerialPortShared(const serialPortConfig_t *portConfig, uint16_t functionM
|
||||||
|
|
||||||
serialPort_t *findSharedSerialPort(uint16_t functionMask, serialPortFunction_e sharedWithFunction)
|
serialPort_t *findSharedSerialPort(uint16_t functionMask, serialPortFunction_e sharedWithFunction)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < SERIAL_PORT_COUNT; i++) {
|
for (unsigned i = 0; i < ARRAYLEN(serialConfig()->portConfigs); i++) {
|
||||||
const serialPortConfig_t *candidate = &serialConfig()->portConfigs[i];
|
const serialPortConfig_t *candidate = &serialConfig()->portConfigs[i];
|
||||||
|
|
||||||
if (isSerialPortShared(candidate, functionMask, sharedWithFunction)) {
|
if (isSerialPortShared(candidate, functionMask, sharedWithFunction)) {
|
||||||
|
@ -338,12 +412,11 @@ bool isSerialConfigValid(serialConfig_t *serialConfigToCheck)
|
||||||
*/
|
*/
|
||||||
uint8_t mspPortCount = 0;
|
uint8_t mspPortCount = 0;
|
||||||
|
|
||||||
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
for (unsigned index = 0; index < ARRAYLEN(serialConfigToCheck->portConfigs); index++) {
|
||||||
const serialPortConfig_t *portConfig = &serialConfigToCheck->portConfigs[index];
|
const serialPortConfig_t *portConfig = &serialConfigToCheck->portConfigs[index];
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
#ifdef USE_SOFTSERIAL
|
||||||
if ((portConfig->identifier == SERIAL_PORT_SOFTSERIAL1) ||
|
if (serialType(portConfig->identifier) == SERIALTYPE_SOFTSERIAL) {
|
||||||
(portConfig->identifier == SERIAL_PORT_SOFTSERIAL2)) {
|
|
||||||
// Ensure MSP or serial RX is not enabled on soft serial ports
|
// Ensure MSP or serial RX is not enabled on soft serial ports
|
||||||
serialConfigToCheck->portConfigs[index].functionMask &= ~(FUNCTION_MSP | FUNCTION_RX_SERIAL);
|
serialConfigToCheck->portConfigs[index].functionMask &= ~(FUNCTION_MSP | FUNCTION_RX_SERIAL);
|
||||||
// Ensure that the baud rate on soft serial ports is limited to 19200
|
// Ensure that the baud rate on soft serial ports is limited to 19200
|
||||||
|
@ -357,12 +430,14 @@ bool isSerialConfigValid(serialConfig_t *serialConfigToCheck)
|
||||||
|
|
||||||
if (portConfig->functionMask & FUNCTION_MSP) {
|
if (portConfig->functionMask & FUNCTION_MSP) {
|
||||||
mspPortCount++;
|
mspPortCount++;
|
||||||
} else if (portConfig->identifier == SERIAL_PORT_USB_VCP) {
|
}
|
||||||
|
if (portConfig->identifier == SERIAL_PORT_USB_VCP
|
||||||
|
&& (portConfig->functionMask & FUNCTION_MSP) == 0) {
|
||||||
// Require MSP to be enabled for the VCP port
|
// Require MSP to be enabled for the VCP port
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t bitCount = BITCOUNT(portConfig->functionMask);
|
uint8_t bitCount = popcount(portConfig->functionMask);
|
||||||
|
|
||||||
#ifdef USE_VTX_MSP
|
#ifdef USE_VTX_MSP
|
||||||
if ((portConfig->functionMask & FUNCTION_VTX_MSP) && bitCount == 1) { // VTX MSP has to be shared with RX or MSP serial
|
if ((portConfig->functionMask & FUNCTION_VTX_MSP) && bitCount == 1) { // VTX MSP has to be shared with RX or MSP serial
|
||||||
|
@ -395,17 +470,6 @@ bool isSerialConfigValid(serialConfig_t *serialConfigToCheck)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const serialPortConfig_t *serialFindPortConfiguration(serialPortIdentifier_e identifier)
|
|
||||||
{
|
|
||||||
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
|
||||||
const serialPortConfig_t *candidate = &serialConfig()->portConfigs[index];
|
|
||||||
if (candidate->identifier == identifier) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool doesConfigurationUsePort(serialPortIdentifier_e identifier)
|
bool doesConfigurationUsePort(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
const serialPortConfig_t *candidate = serialFindPortConfiguration(identifier);
|
const serialPortConfig_t *candidate = serialFindPortConfiguration(identifier);
|
||||||
|
@ -421,7 +485,7 @@ serialPort_t *openSerialPort(
|
||||||
portMode_e mode,
|
portMode_e mode,
|
||||||
portOptions_e options)
|
portOptions_e options)
|
||||||
{
|
{
|
||||||
#if !(defined(USE_UART) || defined(USE_SOFTSERIAL))
|
#if !(defined(USE_UART) || defined(USE_SOFTSERIAL) || defined(USE_LPUART))
|
||||||
UNUSED(rxCallback);
|
UNUSED(rxCallback);
|
||||||
UNUSED(rxCallbackData);
|
UNUSED(rxCallbackData);
|
||||||
UNUSED(baudRate);
|
UNUSED(baudRate);
|
||||||
|
@ -437,71 +501,34 @@ serialPort_t *openSerialPort(
|
||||||
|
|
||||||
serialPort_t *serialPort = NULL;
|
serialPort_t *serialPort = NULL;
|
||||||
|
|
||||||
#if defined(USE_SOFTSERIAL) && !defined(USE_OVERRIDE_SOFTSERIAL_BAUDRATE)
|
switch (serialType(identifier)) {
|
||||||
if (((identifier == SERIAL_PORT_SOFTSERIAL1) || (identifier == SERIAL_PORT_SOFTSERIAL2)) && (baudRate > 19200)) {
|
#if defined(USE_VCP)
|
||||||
// Don't continue if baud rate requested is higher then the limit set on soft serial ports
|
case SERIALTYPE_USB_VCP:
|
||||||
return NULL;
|
serialPort = usbVcpOpen();
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (identifier) {
|
|
||||||
#ifdef USE_VCP
|
|
||||||
case SERIAL_PORT_USB_VCP:
|
|
||||||
serialPort = usbVcpOpen();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_UART)
|
#if defined(USE_UART)
|
||||||
#ifdef USE_UART1
|
case SERIALTYPE_UART:
|
||||||
case SERIAL_PORT_USART1:
|
case SERIALTYPE_LPUART:
|
||||||
#endif
|
|
||||||
#ifdef USE_UART2
|
|
||||||
case SERIAL_PORT_USART2:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART3
|
|
||||||
case SERIAL_PORT_USART3:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART4
|
|
||||||
case SERIAL_PORT_UART4:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART5
|
|
||||||
case SERIAL_PORT_UART5:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART6
|
|
||||||
case SERIAL_PORT_USART6:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART7
|
|
||||||
case SERIAL_PORT_USART7:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART8
|
|
||||||
case SERIAL_PORT_USART8:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART9
|
|
||||||
case SERIAL_PORT_UART9:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_UART10
|
|
||||||
case SERIAL_PORT_USART10:
|
|
||||||
#endif
|
|
||||||
#ifdef USE_LPUART1
|
|
||||||
case SERIAL_PORT_LPUART1:
|
|
||||||
#endif
|
|
||||||
#if defined(SIMULATOR_BUILD)
|
#if defined(SIMULATOR_BUILD)
|
||||||
// emulate serial ports over TCP
|
// emulate serial ports over TCP
|
||||||
serialPort = serTcpOpen(SERIAL_PORT_IDENTIFIER_TO_UARTDEV(identifier), rxCallback, rxCallbackData, baudRate, mode, options);
|
serialPort = serTcpOpen(identifier, rxCallback, rxCallbackData, baudRate, mode, options);
|
||||||
#else
|
#else
|
||||||
serialPort = uartOpen(SERIAL_PORT_IDENTIFIER_TO_UARTDEV(identifier), rxCallback, rxCallbackData, baudRate, mode, options);
|
serialPort = uartOpen(identifier, rxCallback, rxCallbackData, baudRate, mode, options);
|
||||||
#endif
|
#endif
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
#ifdef USE_SOFTSERIAL
|
#ifdef USE_SOFTSERIAL
|
||||||
case SERIAL_PORT_SOFTSERIAL1:
|
case SERIALTYPE_SOFTSERIAL:
|
||||||
serialPort = openSoftSerial(SOFTSERIAL1, rxCallback, rxCallbackData, baudRate, mode, options);
|
# if !defined(USE_OVERRIDE_SOFTSERIAL_BAUDRATE)
|
||||||
break;
|
if (baudRate > 19200) {
|
||||||
case SERIAL_PORT_SOFTSERIAL2:
|
// Don't continue if baud rate requested is higher then the limit set on soft serial ports
|
||||||
serialPort = openSoftSerial(SOFTSERIAL2, rxCallback, rxCallbackData, baudRate, mode, options);
|
return NULL;
|
||||||
break;
|
}
|
||||||
#endif
|
# endif // !USE_OVERRIDE_SOFTSERIAL_BAUDRATE
|
||||||
|
serialPort = softSerialOpen(identifier, rxCallback, rxCallbackData, baudRate, mode, options);
|
||||||
|
break;
|
||||||
|
#endif // USE_SOFTSERIAL
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +537,7 @@ serialPort_t *openSerialPort(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPort->identifier = identifier;
|
serialPort->identifier = identifier; // Some versions of *Open() set this member sooner
|
||||||
|
|
||||||
serialPortUsage->function = function;
|
serialPortUsage->function = function;
|
||||||
serialPortUsage->serialPort = serialPort;
|
serialPortUsage->serialPort = serialPort;
|
||||||
|
@ -545,50 +572,43 @@ void serialInit(bool softserialEnabled, serialPortIdentifier_e serialPortToDisab
|
||||||
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
|
||||||
serialPortUsageList[index].identifier = serialPortIdentifiers[index];
|
serialPortUsageList[index].identifier = serialPortIdentifiers[index];
|
||||||
|
|
||||||
if (serialPortToDisable != SERIAL_PORT_NONE) {
|
if (serialPortToDisable != SERIAL_PORT_NONE
|
||||||
if (serialPortUsageList[index].identifier == serialPortToDisable) {
|
&& serialPortUsageList[index].identifier == serialPortToDisable) {
|
||||||
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
||||||
serialPortCount--;
|
serialPortCount--;
|
||||||
}
|
continue; // this index is deleted
|
||||||
}
|
}
|
||||||
#if !defined(SIMULATOR_BUILD)
|
|
||||||
else if (serialPortUsageList[index].identifier <= SERIAL_PORT_USART10
|
|
||||||
#ifdef USE_LPUART1
|
|
||||||
|| serialPortUsageList[index].identifier == SERIAL_PORT_LPUART1
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
int resourceIndex = SERIAL_PORT_IDENTIFIER_TO_INDEX(serialPortUsageList[index].identifier);
|
|
||||||
if (!(serialPinConfig()->ioTagTx[resourceIndex] || serialPinConfig()->ioTagRx[resourceIndex])) {
|
|
||||||
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
|
||||||
serialPortCount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
else if (((serialPortUsageList[index].identifier == SERIAL_PORT_SOFTSERIAL1) &&
|
|
||||||
(!softserialEnabled || !(softSerialPinConfig()->ioTagRx[SOFTSERIAL1] || softSerialPinConfig()->ioTagTx[SOFTSERIAL1]))) ||
|
|
||||||
((serialPortUsageList[index].identifier == SERIAL_PORT_SOFTSERIAL2) &&
|
|
||||||
(!softserialEnabled || !(softSerialPinConfig()->ioTagRx[SOFTSERIAL2] || softSerialPinConfig()->ioTagTx[SOFTSERIAL2]))))
|
|
||||||
#else
|
|
||||||
else if (
|
|
||||||
(serialPortUsageList[index].identifier == SERIAL_PORT_SOFTSERIAL1) ||
|
|
||||||
(serialPortUsageList[index].identifier == SERIAL_PORT_SOFTSERIAL2)
|
|
||||||
)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
#if !defined(SIMULATOR_BUILD) // no serialPinConfig on SITL
|
||||||
serialPortCount--;
|
const int resourceIndex = serialResourceIndex(serialPortUsageList[index].identifier);
|
||||||
|
if (resourceIndex >= 0 // resource exists
|
||||||
|
&& !(serialPinConfig()->ioTagTx[resourceIndex] || serialPinConfig()->ioTagRx[resourceIndex])) {
|
||||||
|
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
||||||
|
serialPortCount--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (serialType(serialPortUsageList[index].identifier) == SERIALTYPE_SOFTSERIAL) {
|
||||||
|
if (true
|
||||||
|
#ifdef USE_SOFTSERIAL
|
||||||
|
&& !softserialEnabled
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
||||||
|
serialPortCount--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialRemovePort(serialPortIdentifier_e identifier)
|
void serialRemovePort(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
for (uint8_t index = 0; index < SERIAL_PORT_COUNT; index++) {
|
serialPortUsage_t* usage;
|
||||||
if (serialPortUsageList[index].identifier == identifier) {
|
while ((usage = findSerialPortUsageByIdentifier(identifier)) != NULL) {
|
||||||
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
|
usage->identifier = SERIAL_PORT_NONE;
|
||||||
serialPortCount--;
|
serialPortCount--;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,12 +619,7 @@ uint8_t serialGetAvailablePortCount(void)
|
||||||
|
|
||||||
bool serialIsPortAvailable(serialPortIdentifier_e identifier)
|
bool serialIsPortAvailable(serialPortIdentifier_e identifier)
|
||||||
{
|
{
|
||||||
for (uint8_t index = 0; index < SERIAL_PORT_COUNT; index++) {
|
return findSerialPortUsageByIdentifier(identifier) != NULL;
|
||||||
if (serialPortUsageList[index].identifier == identifier) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForSerialPortToFinishTransmitting(serialPort_t *serialPort)
|
void waitForSerialPortToFinishTransmitting(serialPort_t *serialPort)
|
||||||
|
|
|
@ -83,40 +83,46 @@ typedef enum {
|
||||||
SERIAL_PORT_ALL = -2,
|
SERIAL_PORT_ALL = -2,
|
||||||
SERIAL_PORT_NONE = -1,
|
SERIAL_PORT_NONE = -1,
|
||||||
SERIAL_PORT_USART1 = 0,
|
SERIAL_PORT_USART1 = 0,
|
||||||
|
SERIAL_PORT_UART1 = SERIAL_PORT_USART1,
|
||||||
SERIAL_PORT_USART2,
|
SERIAL_PORT_USART2,
|
||||||
|
SERIAL_PORT_UART2 = SERIAL_PORT_USART2,
|
||||||
SERIAL_PORT_USART3,
|
SERIAL_PORT_USART3,
|
||||||
|
SERIAL_PORT_UART3 = SERIAL_PORT_USART3,
|
||||||
SERIAL_PORT_UART4,
|
SERIAL_PORT_UART4,
|
||||||
SERIAL_PORT_UART5,
|
SERIAL_PORT_UART5,
|
||||||
SERIAL_PORT_USART6,
|
SERIAL_PORT_USART6,
|
||||||
|
SERIAL_PORT_UART6 = SERIAL_PORT_USART6,
|
||||||
SERIAL_PORT_USART7,
|
SERIAL_PORT_USART7,
|
||||||
|
SERIAL_PORT_UART7 = SERIAL_PORT_USART7,
|
||||||
SERIAL_PORT_USART8,
|
SERIAL_PORT_USART8,
|
||||||
|
SERIAL_PORT_UART8 = SERIAL_PORT_USART8,
|
||||||
SERIAL_PORT_UART9,
|
SERIAL_PORT_UART9,
|
||||||
SERIAL_PORT_USART10,
|
SERIAL_PORT_USART10,
|
||||||
|
SERIAL_PORT_UART10 = SERIAL_PORT_USART10,
|
||||||
SERIAL_PORT_USART_MAX = SERIAL_PORT_USART10,
|
SERIAL_PORT_USART_MAX = SERIAL_PORT_USART10,
|
||||||
|
|
||||||
SERIAL_PORT_USB_VCP = 20,
|
SERIAL_PORT_USB_VCP = 20,
|
||||||
|
|
||||||
SERIAL_PORT_SOFTSERIAL1 = 30,
|
SERIAL_PORT_SOFTSERIAL1 = 30,
|
||||||
SERIAL_PORT_SOFTSERIAL2,
|
SERIAL_PORT_SOFTSERIAL2,
|
||||||
|
|
||||||
SERIAL_PORT_LPUART1 = 40,
|
SERIAL_PORT_LPUART1 = 40,
|
||||||
SERIAL_PORT_IDENTIFIER_MAX = SERIAL_PORT_LPUART1,
|
|
||||||
} serialPortIdentifier_e;
|
} serialPortIdentifier_e;
|
||||||
|
|
||||||
|
// use value from target serial port normalization
|
||||||
|
#define SERIAL_PORT_COUNT (SERIAL_UART_COUNT + SERIAL_LPUART_COUNT + SERIAL_SOFTSERIAL_COUNT + SERIAL_VCP_COUNT)
|
||||||
|
|
||||||
extern const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT];
|
extern const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT];
|
||||||
|
|
||||||
#define SOFTSERIAL_PORT_IDENTIFIER_TO_INDEX(x) ((x) - SERIAL_PORT_SOFTSERIAL1)
|
typedef enum {
|
||||||
|
SERIALTYPE_INVALID = -1,
|
||||||
|
SERIALTYPE_USB_VCP = 0,
|
||||||
|
SERIALTYPE_UART,
|
||||||
|
SERIALTYPE_LPUART,
|
||||||
|
SERIALTYPE_SOFTSERIAL,
|
||||||
|
SERIALTYPE_COUNT
|
||||||
|
} serialType_e;
|
||||||
|
|
||||||
#if defined(USE_LPUART1)
|
|
||||||
|
|
||||||
#define SERIAL_PORT_IDENTIFIER_TO_INDEX(x) \
|
|
||||||
(((x) <= SERIAL_PORT_USART_MAX) ? ((x) - SERIAL_PORT_USART1) : ((x) - SERIAL_PORT_LPUART1) + LPUARTDEV_1)
|
|
||||||
#define SERIAL_PORT_IDENTIFIER_TO_UARTDEV(x) \
|
|
||||||
(((x) <= SERIAL_PORT_USART_MAX) ? ((x) - SERIAL_PORT_USART1 + UARTDEV_1) : ((x) - SERIAL_PORT_LPUART1) + LPUARTDEV_1)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define SERIAL_PORT_IDENTIFIER_TO_INDEX(x) ((x) - SERIAL_PORT_USART1)
|
|
||||||
#define SERIAL_PORT_IDENTIFIER_TO_UARTDEV(x) ((x) - SERIAL_PORT_USART1 + UARTDEV_1)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
//
|
//
|
||||||
// runtime
|
// runtime
|
||||||
//
|
//
|
||||||
|
@ -170,6 +176,9 @@ bool isSerialPortShared(const serialPortConfig_t *portConfig, uint16_t functionM
|
||||||
void pgResetFn_serialConfig(serialConfig_t *serialConfig); //!!TODO remove need for this
|
void pgResetFn_serialConfig(serialConfig_t *serialConfig); //!!TODO remove need for this
|
||||||
serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier);
|
serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier);
|
||||||
int findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier);
|
int findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier);
|
||||||
|
serialPortIdentifier_e findSerialPortByName(const char* portName, int (*cmp)(const char *portName, const char *candidate));
|
||||||
|
const char* serialName(serialPortIdentifier_e identifier, const char* notFound);
|
||||||
|
|
||||||
//
|
//
|
||||||
// runtime
|
// runtime
|
||||||
//
|
//
|
||||||
|
@ -188,6 +197,10 @@ void waitForSerialPortToFinishTransmitting(serialPort_t *serialPort);
|
||||||
|
|
||||||
baudRate_e lookupBaudRateIndex(uint32_t baudRate);
|
baudRate_e lookupBaudRateIndex(uint32_t baudRate);
|
||||||
|
|
||||||
|
serialType_e serialType(serialPortIdentifier_e identifier);
|
||||||
|
|
||||||
|
// resource index of given identifier, or -1 if not available
|
||||||
|
int serialResourceIndex(serialPortIdentifier_e identifier);
|
||||||
|
|
||||||
//
|
//
|
||||||
// msp/cli/bootloader
|
// msp/cli/bootloader
|
||||||
|
|
128
src/main/io/serial_resource.c
Normal file
128
src/main/io/serial_resource.c
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Betaflight.
|
||||||
|
*
|
||||||
|
* Betaflight is free software. You can redistribute this software
|
||||||
|
* and/or modify this software 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.
|
||||||
|
*
|
||||||
|
* Betaflight 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 this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
|
// convert identifier into port type
|
||||||
|
serialType_e serialType(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
#ifdef USE_VCP
|
||||||
|
if (identifier == SERIAL_PORT_USB_VCP) {
|
||||||
|
return SERIALTYPE_USB_VCP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART
|
||||||
|
if (identifier >= SERIAL_PORT_USART1 && identifier < SERIAL_PORT_USART1 + SERIAL_UART_MAX) {
|
||||||
|
const unsigned idx = identifier - SERIAL_PORT_USART1;
|
||||||
|
if (BIT(idx) & SERIAL_UART_MASK) {
|
||||||
|
return SERIALTYPE_UART;
|
||||||
|
} else {
|
||||||
|
// no other type in this range
|
||||||
|
return SERIALTYPE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef USE_LPUART
|
||||||
|
if (identifier >= SERIAL_PORT_LPUART1 && identifier < SERIAL_PORT_LPUART1 + SERIAL_LPUART_MAX) {
|
||||||
|
const unsigned idx = identifier - SERIAL_PORT_LPUART1;
|
||||||
|
if (BIT(idx) & SERIAL_LPUART_MASK) {
|
||||||
|
return SERIALTYPE_LPUART;
|
||||||
|
} else {
|
||||||
|
// no other type in this range
|
||||||
|
return SERIALTYPE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SOFTSERIAL
|
||||||
|
if (identifier >= SERIAL_PORT_SOFTSERIAL1 && identifier < SERIAL_PORT_SOFTSERIAL1 + SERIAL_SOFTSERIAL_MAX) {
|
||||||
|
// sotserials always start from 1, without holes
|
||||||
|
return SERIALTYPE_SOFTSERIAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SERIALTYPE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct SerialTypeInfo {
|
||||||
|
resourceOwner_e owner;
|
||||||
|
serialPortIdentifier_e firstId;
|
||||||
|
int8_t resourceOffset;
|
||||||
|
} serialTypeMap[] = {
|
||||||
|
[SERIALTYPE_USB_VCP] = { OWNER_FREE /* no owner*/, SERIAL_PORT_USB_VCP, -1 },
|
||||||
|
[SERIALTYPE_UART] = { OWNER_SERIAL_TX, SERIAL_PORT_USART1, RESOURCE_UART_OFFSET },
|
||||||
|
[SERIALTYPE_LPUART] = { OWNER_LPUART_TX, SERIAL_PORT_LPUART1, RESOURCE_LPUART_OFFSET },
|
||||||
|
[SERIALTYPE_SOFTSERIAL] = { OWNER_SOFTSERIAL_TX, SERIAL_PORT_SOFTSERIAL1, RESOURCE_SOFTSERIAL_OFFSET },
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC_ASSERT(ARRAYLEN(serialTypeMap) == SERIALTYPE_COUNT, "type table mismatch");
|
||||||
|
|
||||||
|
static const struct SerialTypeInfo* serialTypeInfo(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
const serialType_e type = serialType(identifier);
|
||||||
|
if (type == SERIALTYPE_INVALID) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return serialTypeMap + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resourceOwner_e for this serial (UART/LPUART/SOFTSERIAL/..)
|
||||||
|
// Used together with serialOwnerIndex to identify claimed resources
|
||||||
|
// Tx member is returned, Rx is always Tx + 1
|
||||||
|
// OWNER_FREE is returned for serials without owner (VCP)
|
||||||
|
resourceOwner_e serialOwnerTxRx(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
|
||||||
|
return inf ? inf->owner : OWNER_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return index used to claim given resource. Returned value is 1 based, for IOInit and similar
|
||||||
|
// 0 is returned when given port is not defined or if it is singleton port (USB)
|
||||||
|
int serialOwnerIndex(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
|
||||||
|
if (!inf || inf->owner == OWNER_FREE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return RESOURCE_INDEX(identifier - inf->firstId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// map identifier into index used to store port resources:
|
||||||
|
// pins(RX,TX), external inversion, port DMA configuration
|
||||||
|
// order is UART, LPUART, SOFTSERIAL, with each group using index
|
||||||
|
// coresponding to port name (UART1 -> 0, UART5 -> 4, but LPUART -> 5 if
|
||||||
|
// there is no UART6 and higher on given target.
|
||||||
|
// -1 is returned if given port is not defined or is not using resources
|
||||||
|
// some code uses this ordering for optimizations, be carefull if reordering is necessary
|
||||||
|
int serialResourceIndex(serialPortIdentifier_e identifier)
|
||||||
|
{
|
||||||
|
const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
|
||||||
|
if (!inf || inf->resourceOffset < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return identifier - inf->firstId + inf->resourceOffset;
|
||||||
|
}
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
|
||||||
#define SMARTAUDIO_SERIAL_OPTIONS SERIAL_NOT_INVERTED | SERIAL_BIDIR_NOPULL | SERIAL_STOPBITS_2
|
|
||||||
#define SMARTAUDIO_DEFAULT_BAUD 4900
|
#define SMARTAUDIO_DEFAULT_BAUD 4900
|
||||||
#define SMARTAUDIO_MIN_BAUD 4800
|
#define SMARTAUDIO_MIN_BAUD 4800
|
||||||
#define SMARTAUDIO_MAX_BAUD 4950
|
#define SMARTAUDIO_MAX_BAUD 4950
|
||||||
|
|
|
@ -39,7 +39,7 @@ typedef struct vtxSettingsConfig_s {
|
||||||
uint16_t freq; // sets freq in MHz if band=0
|
uint16_t freq; // sets freq in MHz if band=0
|
||||||
uint16_t pitModeFreq; // sets out-of-range pitmode frequency
|
uint16_t pitModeFreq; // sets out-of-range pitmode frequency
|
||||||
uint8_t lowPowerDisarm; // min power while disarmed, from vtxLowerPowerDisarm_e
|
uint8_t lowPowerDisarm; // min power while disarmed, from vtxLowerPowerDisarm_e
|
||||||
uint8_t softserialAlt; // pull line low before sending frame even with SOFTSERIAL
|
uint8_t softserialAlt; // prepend 0xff before sending frame even with SOFTSERIAL
|
||||||
} vtxSettingsConfig_t;
|
} vtxSettingsConfig_t;
|
||||||
|
|
||||||
PG_DECLARE(vtxSettingsConfig_t, vtxSettingsConfig);
|
PG_DECLARE(vtxSettingsConfig_t, vtxSettingsConfig);
|
||||||
|
|
|
@ -199,7 +199,7 @@ static void vtxMspProcess(vtxDevice_t *vtxDevice, timeUs_t currentTimeUs)
|
||||||
if (isCrsfPortConfig(portConfig)) {
|
if (isCrsfPortConfig(portConfig)) {
|
||||||
mspCrsfPush(MSP_VTX_CONFIG, frame, sizeof(frame));
|
mspCrsfPush(MSP_VTX_CONFIG, frame, sizeof(frame));
|
||||||
} else {
|
} else {
|
||||||
mspSerialPush((serialPortIdentifier_e) portConfig->identifier, MSP_VTX_CONFIG, frame, sizeof(frame), MSP_DIRECTION_REPLY, MSP_V2_NATIVE);
|
mspSerialPush(portConfig->identifier, MSP_VTX_CONFIG, frame, sizeof(frame), MSP_DIRECTION_REPLY, MSP_V2_NATIVE);
|
||||||
}
|
}
|
||||||
packetCounter++;
|
packetCounter++;
|
||||||
mspVtxLastTimeUs = currentTimeUs;
|
mspVtxLastTimeUs = currentTimeUs;
|
||||||
|
|
|
@ -497,26 +497,34 @@ static void saReceiveFrame(uint8_t c)
|
||||||
static void saSendFrame(uint8_t *buf, int len)
|
static void saSendFrame(uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
if (!IS_RC_MODE_ACTIVE(BOXVTXCONTROLDISABLE)) {
|
if (!IS_RC_MODE_ACTIVE(BOXVTXCONTROLDISABLE)) {
|
||||||
#ifndef AT32F4
|
bool prepend00;
|
||||||
switch (smartAudioSerialPort->identifier) {
|
switch (serialType(smartAudioSerialPort->identifier)) {
|
||||||
case SERIAL_PORT_SOFTSERIAL1:
|
case SERIALTYPE_SOFTSERIAL:
|
||||||
case SERIAL_PORT_SOFTSERIAL2:
|
prepend00 = vtxSettingsConfig()->softserialAlt;
|
||||||
if (vtxSettingsConfig()->softserialAlt) {
|
break;
|
||||||
serialWrite(smartAudioSerialPort, 0x00); // Generate 1st start byte
|
case SERIALTYPE_UART:
|
||||||
}
|
case SERIALTYPE_LPUART: // decide HW uarts by MCU type
|
||||||
|
#ifdef AT32F4
|
||||||
|
prepend00 = false;
|
||||||
|
#else
|
||||||
|
prepend00 = true;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
serialWrite(smartAudioSerialPort, 0x00); // Generate 1st start byte
|
prepend00 = false;
|
||||||
break;
|
}
|
||||||
|
if (prepend00) {
|
||||||
|
// line is in MARK/BREAK, so only 2 stopbits will be visible (startbit and zeroes are not visible)
|
||||||
|
// startbit of next byte (0xaa) can be recognized
|
||||||
|
serialWrite(smartAudioSerialPort, 0x00);
|
||||||
}
|
}
|
||||||
#endif //AT32F4
|
|
||||||
|
|
||||||
for (int i = 0 ; i < len ; i++) {
|
for (int i = 0 ; i < len ; i++) {
|
||||||
serialWrite(smartAudioSerialPort, buf[i]);
|
serialWrite(smartAudioSerialPort, buf[i]);
|
||||||
}
|
}
|
||||||
#ifdef USE_AKK_SMARTAUDIO
|
#ifdef USE_AKK_SMARTAUDIO
|
||||||
serialWrite(smartAudioSerialPort, 0x00); // AKK/RDQ SmartAudio devices can expect an extra byte due to manufacturing errors.
|
serialWrite(smartAudioSerialPort, 0x00); // AKK/RDQ SmartAudio devices can expect an extra byte due to manufacturing errors.
|
||||||
#endif // USE_AKK_SMARTAUDIO
|
#endif
|
||||||
|
|
||||||
saStat.pktsent++;
|
saStat.pktsent++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -705,20 +713,15 @@ bool vtxSmartAudioInit(void)
|
||||||
dprintf(("smartAudioInit: OK\r\n"));
|
dprintf(("smartAudioInit: OK\r\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Note, for SA, which uses bidirectional mode, would normally require pullups.
|
|
||||||
// the SA protocol instead requires pulldowns, and therefore uses SERIAL_BIDIR_PP_PD instead of SERIAL_BIDIR_PP
|
|
||||||
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_VTX_SMARTAUDIO);
|
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_VTX_SMARTAUDIO);
|
||||||
if (portConfig) {
|
if (!portConfig) {
|
||||||
portOptions_e portOptions = SERIAL_STOPBITS_2 | SERIAL_BIDIR | SERIAL_BIDIR_PP_PD | SERIAL_BIDIR_NOPULL;
|
return false;
|
||||||
#ifdef USE_SMARTAUDIO_NOPULLDOWN
|
|
||||||
// softserial hack (#13797)
|
|
||||||
if (smartAudioSerialPort->identifier == SERIAL_PORT_SOFTSERIAL1 || smartAudioSerialPort->identifier == SERIAL_PORT_SOFTSERIAL2) {
|
|
||||||
portOptions &= ~SERIAL_BIDIR_PP_PD;
|
|
||||||
portOptions |= SERIAL_BIDIR_PP;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
smartAudioSerialPort = openSerialPort(portConfig->identifier, FUNCTION_VTX_SMARTAUDIO, NULL, NULL, 4800, MODE_RXTX, portOptions);
|
|
||||||
}
|
}
|
||||||
|
// Note, for SA, which uses bidirectional mode, would normally require pullups.
|
||||||
|
// the SA protocol usually requires pulldowns, and therefore uses SERIAL_PULL_SMARTAUDIO together with SERIAL_BIDIR_PP
|
||||||
|
// serial driver handles different pullup/pulldown/nopull quirks when SERIAL_PULL_SMARTAUDIO is used
|
||||||
|
const portOptions_e portOptions = SERIAL_NOT_INVERTED | SERIAL_STOPBITS_2 | SERIAL_BIDIR | SERIAL_BIDIR_PP | SERIAL_PULL_SMARTAUDIO;
|
||||||
|
smartAudioSerialPort = openSerialPort(portConfig->identifier, FUNCTION_VTX_SMARTAUDIO, NULL, NULL, 4800, MODE_RXTX, portOptions);
|
||||||
|
|
||||||
if (!smartAudioSerialPort) {
|
if (!smartAudioSerialPort) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -654,9 +654,9 @@ bool vtxTrampInit(void)
|
||||||
if (portConfig) {
|
if (portConfig) {
|
||||||
portOptions_e portOptions = 0;
|
portOptions_e portOptions = 0;
|
||||||
#if defined(USE_VTX_COMMON)
|
#if defined(USE_VTX_COMMON)
|
||||||
portOptions = portOptions | (vtxConfig()->halfDuplex ? SERIAL_BIDIR : SERIAL_UNIDIR);
|
portOptions |= vtxConfig()->halfDuplex ? SERIAL_BIDIR : 0;
|
||||||
#else
|
#else
|
||||||
portOptions = SERIAL_BIDIR;
|
portOptions |= SERIAL_BIDIR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
trampSerialPort = openSerialPort(portConfig->identifier, FUNCTION_VTX_TRAMP, NULL, NULL, 9600, MODE_RXTX, portOptions);
|
trampSerialPort = openSerialPort(portConfig->identifier, FUNCTION_VTX_TRAMP, NULL, NULL, 9600, MODE_RXTX, portOptions);
|
||||||
|
|
|
@ -57,7 +57,7 @@ void mspSerialAllocatePorts(void)
|
||||||
{
|
{
|
||||||
uint8_t portIndex = 0;
|
uint8_t portIndex = 0;
|
||||||
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_MSP);
|
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_MSP);
|
||||||
while (portConfig && portIndex < MAX_MSP_PORT_COUNT) {
|
while (portConfig && portIndex < ARRAYLEN(mspPorts)) {
|
||||||
mspPort_t *mspPort = &mspPorts[portIndex];
|
mspPort_t *mspPort = &mspPorts[portIndex];
|
||||||
|
|
||||||
if (mspPort->port) {
|
if (mspPort->port) {
|
||||||
|
@ -69,7 +69,8 @@ void mspSerialAllocatePorts(void)
|
||||||
|
|
||||||
if (mspConfig()->halfDuplex) {
|
if (mspConfig()->halfDuplex) {
|
||||||
options |= SERIAL_BIDIR;
|
options |= SERIAL_BIDIR;
|
||||||
} else if ((portConfig->identifier >= SERIAL_PORT_USART1) && (portConfig->identifier <= SERIAL_PORT_USART_MAX)){
|
} else if (serialType(portConfig->identifier) == SERIALTYPE_UART
|
||||||
|
|| serialType(portConfig->identifier) == SERIALTYPE_LPUART) {
|
||||||
options |= SERIAL_CHECK_TX;
|
options |= SERIAL_CHECK_TX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ void mspSerialAllocatePorts(void)
|
||||||
|
|
||||||
void mspSerialReleasePortIfAllocated(serialPort_t *serialPort)
|
void mspSerialReleasePortIfAllocated(serialPort_t *serialPort)
|
||||||
{
|
{
|
||||||
for (uint8_t portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
||||||
if (candidateMspPort->port == serialPort) {
|
if (candidateMspPort->port == serialPort) {
|
||||||
closeSerialPort(serialPort);
|
closeSerialPort(serialPort);
|
||||||
|
@ -96,11 +97,11 @@ void mspSerialReleasePortIfAllocated(serialPort_t *serialPort)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mspDescriptor_t getMspSerialPortDescriptor(const uint8_t portIdentifier)
|
mspDescriptor_t getMspSerialPortDescriptor(const serialPortIdentifier_e portIdentifier)
|
||||||
{
|
{
|
||||||
for (uint8_t portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
||||||
if (candidateMspPort->port->identifier == portIdentifier) {
|
if (candidateMspPort->port && candidateMspPort->port->identifier == portIdentifier) {
|
||||||
return candidateMspPort->descriptor;
|
return candidateMspPort->descriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +111,7 @@ mspDescriptor_t getMspSerialPortDescriptor(const uint8_t portIdentifier)
|
||||||
#if defined(USE_TELEMETRY)
|
#if defined(USE_TELEMETRY)
|
||||||
void mspSerialReleaseSharedTelemetryPorts(void)
|
void mspSerialReleaseSharedTelemetryPorts(void)
|
||||||
{
|
{
|
||||||
for (uint8_t portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
mspPort_t *candidateMspPort = &mspPorts[portIndex];
|
||||||
if (candidateMspPort->sharedWithTelemetry) {
|
if (candidateMspPort->sharedWithTelemetry) {
|
||||||
closeSerialPort(candidateMspPort->port);
|
closeSerialPort(candidateMspPort->port);
|
||||||
|
@ -520,7 +521,7 @@ void mspProcessPacket(mspPort_t *mspPort, mspProcessCommandFnPtr mspProcessComma
|
||||||
*/
|
*/
|
||||||
void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessCommandFnPtr mspProcessCommandFn, mspProcessReplyFnPtr mspProcessReplyFn)
|
void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessCommandFnPtr mspProcessCommandFn, mspProcessReplyFnPtr mspProcessReplyFn)
|
||||||
{
|
{
|
||||||
for (uint8_t portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t * const mspPort = &mspPorts[portIndex];
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
if (!mspPort->port) {
|
if (!mspPort->port) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -576,7 +577,7 @@ void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessComm
|
||||||
|
|
||||||
bool mspSerialWaiting(void)
|
bool mspSerialWaiting(void)
|
||||||
{
|
{
|
||||||
for (uint8_t portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t * const mspPort = &mspPorts[portIndex];
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
if (!mspPort->port) {
|
if (!mspPort->port) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -599,7 +600,7 @@ int mspSerialPush(serialPortIdentifier_e port, uint8_t cmd, uint8_t *data, int d
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (int portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t * const mspPort = &mspPorts[portIndex];
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
|
|
||||||
// XXX Kludge!!! Avoid zombie VCP port (avoid VCP entirely for now)
|
// XXX Kludge!!! Avoid zombie VCP port (avoid VCP entirely for now)
|
||||||
|
@ -628,7 +629,7 @@ uint32_t mspSerialTxBytesFree(void)
|
||||||
{
|
{
|
||||||
uint32_t ret = UINT32_MAX;
|
uint32_t ret = UINT32_MAX;
|
||||||
|
|
||||||
for (int portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
for (unsigned portIndex = 0; portIndex < ARRAYLEN(mspPorts); portIndex++) {
|
||||||
mspPort_t * const mspPort = &mspPorts[portIndex];
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
if (!mspPort->port) {
|
if (!mspPort->port) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -128,6 +128,6 @@ void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessComm
|
||||||
void mspSerialAllocatePorts(void);
|
void mspSerialAllocatePorts(void);
|
||||||
void mspSerialReleasePortIfAllocated(struct serialPort_s *serialPort);
|
void mspSerialReleasePortIfAllocated(struct serialPort_s *serialPort);
|
||||||
void mspSerialReleaseSharedTelemetryPorts(void);
|
void mspSerialReleaseSharedTelemetryPorts(void);
|
||||||
mspDescriptor_t getMspSerialPortDescriptor(const uint8_t portIdentifier);
|
mspDescriptor_t getMspSerialPortDescriptor(const serialPortIdentifier_e portIdentifier);
|
||||||
int mspSerialPush(serialPortIdentifier_e port, uint8_t cmd, uint8_t *data, int datalen, mspDirection_e direction, mspVersion_e mspVersion);
|
int mspSerialPush(serialPortIdentifier_e port, uint8_t cmd, uint8_t *data, int datalen, mspDirection_e direction, mspVersion_e mspVersion);
|
||||||
uint32_t mspSerialTxBytesFree(void);
|
uint32_t mspSerialTxBytesFree(void);
|
||||||
|
|
|
@ -157,8 +157,8 @@
|
||||||
#define PG_RX_EXPRESSLRS_SPI_CONFIG 555
|
#define PG_RX_EXPRESSLRS_SPI_CONFIG 555
|
||||||
#define PG_SCHEDULER_CONFIG 556
|
#define PG_SCHEDULER_CONFIG 556
|
||||||
#define PG_MSP_CONFIG 557
|
#define PG_MSP_CONFIG 557
|
||||||
#define PG_SOFTSERIAL_PIN_CONFIG 558
|
//#define PG_SOFTSERIAL_PIN_CONFIG 558 // removed, merged into SERIAL_PIN_CONFIG
|
||||||
#define PG_BETAFLIGHT_END 558
|
#define PG_BETAFLIGHT_END 557
|
||||||
|
|
||||||
|
|
||||||
// OSD configuration (subject to change)
|
// OSD configuration (subject to change)
|
||||||
|
|
|
@ -34,49 +34,50 @@
|
||||||
#include "drivers/io_types.h"
|
#include "drivers/io_types.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
|
#include "drivers/dma_reqmap.h"
|
||||||
|
|
||||||
// TODO(hertz@): UARTDEV_CONFIG_MAX is measured to be exactly 8, which cannot accomodate even all the UARTs below
|
// TODO(hertz@): UARTDEV_CONFIG_MAX is measured to be exactly 8, which cannot accomodate even all the UARTs below
|
||||||
PG_REGISTER_ARRAY_WITH_RESET_FN(serialUartConfig_t, UARTDEV_CONFIG_MAX, serialUartConfig, PG_SERIAL_UART_CONFIG, 0);
|
PG_REGISTER_ARRAY_WITH_RESET_FN(serialUartConfig_t, UARTDEV_CONFIG_MAX, serialUartConfig, PG_SERIAL_UART_CONFIG, 0);
|
||||||
|
|
||||||
typedef struct uartDmaopt_s {
|
typedef struct uartDmaopt_s {
|
||||||
UARTDevice_e device;
|
serialPortIdentifier_e identifier;
|
||||||
int8_t txDmaopt;
|
int8_t txDmaopt;
|
||||||
int8_t rxDmaopt;
|
int8_t rxDmaopt;
|
||||||
} uartDmaopt_t;
|
} uartDmaopt_t;
|
||||||
|
|
||||||
static uartDmaopt_t uartDmaopt[] = {
|
static const uartDmaopt_t uartDmaopt[] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{ UARTDEV_1, UART1_TX_DMA_OPT, UART1_RX_DMA_OPT },
|
{ SERIAL_PORT_USART1, UART1_TX_DMA_OPT, UART1_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{ UARTDEV_2, UART2_TX_DMA_OPT, UART2_RX_DMA_OPT },
|
{ SERIAL_PORT_USART2, UART2_TX_DMA_OPT, UART2_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{ UARTDEV_3, UART3_TX_DMA_OPT, UART3_RX_DMA_OPT },
|
{ SERIAL_PORT_USART3, UART3_TX_DMA_OPT, UART3_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{ UARTDEV_4, UART4_TX_DMA_OPT, UART4_RX_DMA_OPT },
|
{ SERIAL_PORT_UART4, UART4_TX_DMA_OPT, UART4_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{ UARTDEV_5, UART5_TX_DMA_OPT, UART5_RX_DMA_OPT },
|
{ SERIAL_PORT_UART5, UART5_TX_DMA_OPT, UART5_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART6
|
#ifdef USE_USART6
|
||||||
{ UARTDEV_6, UART6_TX_DMA_OPT, UART6_RX_DMA_OPT },
|
{ SERIAL_PORT_UART6, UART6_TX_DMA_OPT, UART6_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART7
|
#ifdef USE_USART7
|
||||||
{ UARTDEV_7, UART7_TX_DMA_OPT, UART7_RX_DMA_OPT },
|
{ SERIAL_PORT_UART7, UART7_TX_DMA_OPT, UART7_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART8
|
#ifdef USE_USART8
|
||||||
{ UARTDEV_8, UART8_TX_DMA_OPT, UART8_RX_DMA_OPT },
|
{ SERIAL_PORT_UART8, UART8_TX_DMA_OPT, UART8_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART9
|
#ifdef USE_UART9
|
||||||
{ UARTDEV_9, UART9_TX_DMA_OPT, UART9_RX_DMA_OPT },
|
{ SERIAL_PORT_UART9, UART9_TX_DMA_OPT, UART9_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UART10
|
#ifdef USE_UART10
|
||||||
{ UARTDEV_10, UART10_TX_DMA_OPT, UART10_RX_DMA_OPT },
|
{ SERIAL_PORT_UART10, UART10_TX_DMA_OPT, UART10_RX_DMA_OPT },
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
{ LPUARTDEV_1, DMA_OPT_UNUSED, DMA_OPT_UNUSED },
|
{ SERIAL_PORT_LPUART1, DMA_OPT_UNUSED, DMA_OPT_UNUSED },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,9 +89,11 @@ void pgResetFn_serialUartConfig(serialUartConfig_t *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < ARRAYLEN(uartDmaopt); i++) {
|
for (unsigned i = 0; i < ARRAYLEN(uartDmaopt); i++) {
|
||||||
UARTDevice_e device = uartDmaopt[i].device;
|
const int resourceIndex = serialResourceIndex(uartDmaopt[i].identifier);
|
||||||
config[device].txDmaopt = uartDmaopt[i].txDmaopt;
|
if (resourceIndex >= 0 && resourceIndex < UARTDEV_CONFIG_MAX) { // hadle corrupted config gracefuly
|
||||||
config[device].rxDmaopt = uartDmaopt[i].rxDmaopt;
|
config[resourceIndex].txDmaopt = uartDmaopt[i].txDmaopt;
|
||||||
|
config[resourceIndex].rxDmaopt = uartDmaopt[i].rxDmaopt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,12 +24,9 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "pg/pg.h"
|
#include "pg/pg.h"
|
||||||
#include "drivers/io_types.h"
|
#include "drivers/serial_resource.h"
|
||||||
#include "drivers/dma_reqmap.h"
|
|
||||||
|
|
||||||
|
#define UARTDEV_CONFIG_MAX (RESOURCE_UART_COUNT + RESOURCE_LPUART_COUNT)
|
||||||
// TODO(hertz@): this alternative got out of sync
|
|
||||||
#define UARTDEV_CONFIG_MAX 11 // Alternative to UARTDEV_COUNT_MAX, which requires serial_uart_imp.h
|
|
||||||
|
|
||||||
typedef struct serialUartConfig_s {
|
typedef struct serialUartConfig_s {
|
||||||
int8_t txDmaopt;
|
int8_t txDmaopt;
|
||||||
|
|
|
@ -231,7 +231,7 @@ bool ibusInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
|
||||||
NULL,
|
NULL,
|
||||||
IBUS_BAUDRATE,
|
IBUS_BAUDRATE,
|
||||||
portShared ? MODE_RXTX : MODE_RX,
|
portShared ? MODE_RXTX : MODE_RX,
|
||||||
(rxConfig->serialrx_inverted ? SERIAL_INVERTED : 0) | (rxConfig->halfDuplex || portShared ? SERIAL_BIDIR : 0)
|
(rxConfig->serialrx_inverted ? SERIAL_INVERTED : SERIAL_NOT_INVERTED) | ((rxConfig->halfDuplex || portShared) ? SERIAL_BIDIR : 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
#if defined(USE_TELEMETRY) && defined(USE_TELEMETRY_IBUS)
|
#if defined(USE_TELEMETRY) && defined(USE_TELEMETRY_IBUS)
|
||||||
|
|
|
@ -189,13 +189,17 @@ bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
|
||||||
bool portShared = false;
|
bool portShared = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On SBUS, SERIAL_INVERTED is default
|
||||||
|
const portOptions_e portOptions = SBUS_PORT_OPTIONS
|
||||||
|
| (rxConfig->serialrx_inverted ? SERIAL_NOT_INVERTED : SERIAL_INVERTED)
|
||||||
|
| (rxConfig->halfDuplex ? SERIAL_BIDIR : 0);
|
||||||
serialPort_t *sBusPort = openSerialPort(portConfig->identifier,
|
serialPort_t *sBusPort = openSerialPort(portConfig->identifier,
|
||||||
FUNCTION_RX_SERIAL,
|
FUNCTION_RX_SERIAL,
|
||||||
sbusDataReceive,
|
sbusDataReceive,
|
||||||
&sbusFrameData,
|
&sbusFrameData,
|
||||||
sbusBaudRate,
|
sbusBaudRate,
|
||||||
portShared ? MODE_RXTX : MODE_RX,
|
portShared ? MODE_RXTX : MODE_RX,
|
||||||
SBUS_PORT_OPTIONS | (rxConfig->serialrx_inverted ? 0 : SERIAL_INVERTED) | (rxConfig->halfDuplex ? SERIAL_BIDIR : 0)
|
portOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
if (rxConfig->rssi_src_frame_errors) {
|
if (rxConfig->rssi_src_frame_errors) {
|
||||||
|
|
|
@ -238,9 +238,9 @@ void spektrumBind(rxConfig_t *rxConfig)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = SERIAL_PORT_IDENTIFIER_TO_INDEX(portConfig->identifier);
|
const int resourceIndex = serialResourceIndex(portConfig->identifier);
|
||||||
ioTag_t txPin = serialPinConfig()->ioTagTx[index];
|
const ioTag_t txPin = serialPinConfig()->ioTagTx[resourceIndex];
|
||||||
ioTag_t rxPin = serialPinConfig()->ioTagRx[index];
|
const ioTag_t rxPin = serialPinConfig()->ioTagRx[resourceIndex];
|
||||||
|
|
||||||
// Take care half-duplex case
|
// Take care half-duplex case
|
||||||
switch (rxRuntimeState.serialrxProvider) {
|
switch (rxRuntimeState.serialrxProvider) {
|
||||||
|
|
|
@ -386,5 +386,5 @@ void voltageStableUpdate(voltageMeter_t* vm)
|
||||||
// voltage is stable when it was within VOLTAGE_STABLE_MAX_DELTA for 10 update periods
|
// voltage is stable when it was within VOLTAGE_STABLE_MAX_DELTA for 10 update periods
|
||||||
bool voltageIsStable(voltageMeter_t* vm)
|
bool voltageIsStable(voltageMeter_t* vm)
|
||||||
{
|
{
|
||||||
return __builtin_popcount(vm->voltageStableBits & (BIT(VOLTAGE_STABLE_BITS_TOTAL + 1) - 1)) >= VOLTAGE_STABLE_BITS_THRESHOLD;
|
return popcount(vm->voltageStableBits & (BIT(VOLTAGE_STABLE_BITS_TOTAL + 1) - 1)) >= VOLTAGE_STABLE_BITS_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,16 +94,6 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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)
|
|
||||||
#define USE_UART
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART
|
|
||||||
#if defined(INVERTER_PIN_UART1) || defined(INVERTER_PIN_UART2) || defined(INVERTER_PIN_UART3) || defined(INVERTER_PIN_UART4) || defined(INVERTER_PIN_UART5) || defined(INVERTER_PIN_UART6)
|
|
||||||
#define USE_INVERTER
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DEFAULT_MIXER
|
#ifndef DEFAULT_MIXER
|
||||||
#define DEFAULT_MIXER MIXER_QUADX
|
#define DEFAULT_MIXER MIXER_QUADX
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -85,6 +85,10 @@
|
||||||
In the future we can move to specific drivers being added only - to save flash space.
|
In the future we can move to specific drivers being added only - to save flash space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// normalize serial ports definitions
|
||||||
|
#include "serial_post.h"
|
||||||
|
|
||||||
#if defined(USE_MAG) && !defined(USE_VIRTUAL_MAG)
|
#if defined(USE_MAG) && !defined(USE_VIRTUAL_MAG)
|
||||||
|
|
||||||
#ifndef USE_MAG_DATA_READY_SIGNAL
|
#ifndef USE_MAG_DATA_READY_SIGNAL
|
||||||
|
|
523
src/main/target/serial_post.h
Normal file
523
src/main/target/serial_post.h
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Betaflight.
|
||||||
|
*
|
||||||
|
* Betaflight is free software. You can redistribute this software
|
||||||
|
* and/or modify this software 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.
|
||||||
|
*
|
||||||
|
* Betaflight 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 this software.
|
||||||
|
*
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is automatically generated by src/utils/gen-serial.py script from src/utils/templates/serial_post.h jinja2 template.
|
||||||
|
Do not modify this file directly, your changes will be eventually lost.
|
||||||
|
See template file for aditional documentation.
|
||||||
|
|
||||||
|
To generate this file again, run
|
||||||
|
> python ./src/utils/gen-serial-j2.py > ./src/main/target/serial_post.h
|
||||||
|
in Betaflight topmost directory.
|
||||||
|
|
||||||
|
This include will provide following defines:
|
||||||
|
SERIAL_<type><n>_USED 0/1 - always defined, value depends on target configuration
|
||||||
|
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>1 is BIT(0)
|
||||||
|
SERIAL_<type>_COUNT - number of enabled ports of given type
|
||||||
|
SERIAL_<type>_MAX - <index of highest used port> + 1, 0 when no port is enabled
|
||||||
|
|
||||||
|
All <type><n>_(RX|TX)_PINS are normalized too:
|
||||||
|
- if port is enabled, both will be defined (possibly as NONE)
|
||||||
|
- if port is not enable, both will be undefined, possibly with warning
|
||||||
|
- pass -DWARN_UNUSED_SERIAL_PORT to compiler to check pin defined without corresponding port being enabled.
|
||||||
|
|
||||||
|
Generated on 2024-11-04
|
||||||
|
|
||||||
|
Configuration used:
|
||||||
|
{ 'LPUART': {'depends': {'UART'}, 'ids': [1]},
|
||||||
|
'SOFTSERIAL': { 'force_continuous': True,
|
||||||
|
'ids': [1, 2],
|
||||||
|
'use_enables_all': True},
|
||||||
|
'UART': {'ids': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'inverter': True},
|
||||||
|
'VCP': {'no_pins': True, 'singleton': True}}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/utils.h" // BIT, LOG2
|
||||||
|
|
||||||
|
/**** UART *****/
|
||||||
|
|
||||||
|
#if defined(USE_UART1)
|
||||||
|
# define SERIAL_UART1_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART1_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART2)
|
||||||
|
# define SERIAL_UART2_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART2_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART3)
|
||||||
|
# define SERIAL_UART3_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART3_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART4)
|
||||||
|
# define SERIAL_UART4_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART4_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART5)
|
||||||
|
# define SERIAL_UART5_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART5_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART6)
|
||||||
|
# define SERIAL_UART6_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART6_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART7)
|
||||||
|
# define SERIAL_UART7_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART7_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART8)
|
||||||
|
# define SERIAL_UART8_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART8_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART9)
|
||||||
|
# define SERIAL_UART9_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART9_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_UART10)
|
||||||
|
# define SERIAL_UART10_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_UART10_USED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SERIAL_UART_MASK ((SERIAL_UART1_USED * BIT(1 - 1)) | (SERIAL_UART2_USED * BIT(2 - 1)) | (SERIAL_UART3_USED * BIT(3 - 1)) | (SERIAL_UART4_USED * BIT(4 - 1)) | (SERIAL_UART5_USED * BIT(5 - 1)) | (SERIAL_UART6_USED * BIT(6 - 1)) | (SERIAL_UART7_USED * BIT(7 - 1)) | (SERIAL_UART8_USED * BIT(8 - 1)) | (SERIAL_UART9_USED * BIT(9 - 1)) | (SERIAL_UART10_USED * BIT(10 - 1)))
|
||||||
|
#define SERIAL_UART_COUNT (SERIAL_UART1_USED + SERIAL_UART2_USED + SERIAL_UART3_USED + SERIAL_UART4_USED + SERIAL_UART5_USED + SERIAL_UART6_USED + SERIAL_UART7_USED + SERIAL_UART8_USED + SERIAL_UART9_USED + SERIAL_UART10_USED)
|
||||||
|
// 0 if no port is defined
|
||||||
|
#define SERIAL_UART_MAX (SERIAL_UART_MASK ? LOG2(SERIAL_UART_MASK) + 1 : 0)
|
||||||
|
|
||||||
|
|
||||||
|
// enable USE_INVERTED first, before normalization
|
||||||
|
#if !defined(USE_INVERTER) && (INVERTER_PIN_UART1 || INVERTER_PIN_UART2 || INVERTER_PIN_UART3 || INVERTER_PIN_UART4 || INVERTER_PIN_UART5 || INVERTER_PIN_UART6 || INVERTER_PIN_UART7 || INVERTER_PIN_UART8 || INVERTER_PIN_UART9 || INVERTER_PIN_UART10)
|
||||||
|
# define USE_INVERTER
|
||||||
|
#endif
|
||||||
|
// Normalize UART TX/RX/INVERTER
|
||||||
|
#if SERIAL_UART1_USED && !defined(UART1_RX_PIN)
|
||||||
|
# define UART1_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART1_USED && defined(UART1_RX_PIN)
|
||||||
|
# warning "UART1_RX_PIN is defined but UART1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART1_USED && defined(UART1_RX_PIN)
|
||||||
|
# undef UART1_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART1_USED && !defined(UART1_TX_PIN)
|
||||||
|
# define UART1_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART1_USED && defined(UART1_TX_PIN)
|
||||||
|
# warning "UART1_TX_PIN is defined but UART1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART1_USED && defined(UART1_TX_PIN)
|
||||||
|
# undef UART1_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART1_USED && !defined(INVERTER_PIN_UART1)
|
||||||
|
# define INVERTER_PIN_UART1 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART1_USED && defined(INVERTER_PIN_UART1)
|
||||||
|
# warning "INVERTER_PIN_UART1 is defined but UART1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART1_USED && defined(INVERTER_PIN_UART1)
|
||||||
|
# undef INVERTER_PIN_UART1
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART2_USED && !defined(UART2_RX_PIN)
|
||||||
|
# define UART2_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART2_USED && defined(UART2_RX_PIN)
|
||||||
|
# warning "UART2_RX_PIN is defined but UART2 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART2_USED && defined(UART2_RX_PIN)
|
||||||
|
# undef UART2_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART2_USED && !defined(UART2_TX_PIN)
|
||||||
|
# define UART2_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART2_USED && defined(UART2_TX_PIN)
|
||||||
|
# warning "UART2_TX_PIN is defined but UART2 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART2_USED && defined(UART2_TX_PIN)
|
||||||
|
# undef UART2_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART2_USED && !defined(INVERTER_PIN_UART2)
|
||||||
|
# define INVERTER_PIN_UART2 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART2_USED && defined(INVERTER_PIN_UART2)
|
||||||
|
# warning "INVERTER_PIN_UART2 is defined but UART2 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART2_USED && defined(INVERTER_PIN_UART2)
|
||||||
|
# undef INVERTER_PIN_UART2
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART3_USED && !defined(UART3_RX_PIN)
|
||||||
|
# define UART3_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART3_USED && defined(UART3_RX_PIN)
|
||||||
|
# warning "UART3_RX_PIN is defined but UART3 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART3_USED && defined(UART3_RX_PIN)
|
||||||
|
# undef UART3_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART3_USED && !defined(UART3_TX_PIN)
|
||||||
|
# define UART3_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART3_USED && defined(UART3_TX_PIN)
|
||||||
|
# warning "UART3_TX_PIN is defined but UART3 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART3_USED && defined(UART3_TX_PIN)
|
||||||
|
# undef UART3_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART3_USED && !defined(INVERTER_PIN_UART3)
|
||||||
|
# define INVERTER_PIN_UART3 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART3_USED && defined(INVERTER_PIN_UART3)
|
||||||
|
# warning "INVERTER_PIN_UART3 is defined but UART3 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART3_USED && defined(INVERTER_PIN_UART3)
|
||||||
|
# undef INVERTER_PIN_UART3
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART4_USED && !defined(UART4_RX_PIN)
|
||||||
|
# define UART4_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART4_USED && defined(UART4_RX_PIN)
|
||||||
|
# warning "UART4_RX_PIN is defined but UART4 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART4_USED && defined(UART4_RX_PIN)
|
||||||
|
# undef UART4_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART4_USED && !defined(UART4_TX_PIN)
|
||||||
|
# define UART4_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART4_USED && defined(UART4_TX_PIN)
|
||||||
|
# warning "UART4_TX_PIN is defined but UART4 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART4_USED && defined(UART4_TX_PIN)
|
||||||
|
# undef UART4_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART4_USED && !defined(INVERTER_PIN_UART4)
|
||||||
|
# define INVERTER_PIN_UART4 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART4_USED && defined(INVERTER_PIN_UART4)
|
||||||
|
# warning "INVERTER_PIN_UART4 is defined but UART4 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART4_USED && defined(INVERTER_PIN_UART4)
|
||||||
|
# undef INVERTER_PIN_UART4
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART5_USED && !defined(UART5_RX_PIN)
|
||||||
|
# define UART5_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART5_USED && defined(UART5_RX_PIN)
|
||||||
|
# warning "UART5_RX_PIN is defined but UART5 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART5_USED && defined(UART5_RX_PIN)
|
||||||
|
# undef UART5_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART5_USED && !defined(UART5_TX_PIN)
|
||||||
|
# define UART5_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART5_USED && defined(UART5_TX_PIN)
|
||||||
|
# warning "UART5_TX_PIN is defined but UART5 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART5_USED && defined(UART5_TX_PIN)
|
||||||
|
# undef UART5_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART5_USED && !defined(INVERTER_PIN_UART5)
|
||||||
|
# define INVERTER_PIN_UART5 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART5_USED && defined(INVERTER_PIN_UART5)
|
||||||
|
# warning "INVERTER_PIN_UART5 is defined but UART5 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART5_USED && defined(INVERTER_PIN_UART5)
|
||||||
|
# undef INVERTER_PIN_UART5
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART6_USED && !defined(UART6_RX_PIN)
|
||||||
|
# define UART6_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART6_USED && defined(UART6_RX_PIN)
|
||||||
|
# warning "UART6_RX_PIN is defined but UART6 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART6_USED && defined(UART6_RX_PIN)
|
||||||
|
# undef UART6_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART6_USED && !defined(UART6_TX_PIN)
|
||||||
|
# define UART6_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART6_USED && defined(UART6_TX_PIN)
|
||||||
|
# warning "UART6_TX_PIN is defined but UART6 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART6_USED && defined(UART6_TX_PIN)
|
||||||
|
# undef UART6_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART6_USED && !defined(INVERTER_PIN_UART6)
|
||||||
|
# define INVERTER_PIN_UART6 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART6_USED && defined(INVERTER_PIN_UART6)
|
||||||
|
# warning "INVERTER_PIN_UART6 is defined but UART6 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART6_USED && defined(INVERTER_PIN_UART6)
|
||||||
|
# undef INVERTER_PIN_UART6
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART7_USED && !defined(UART7_RX_PIN)
|
||||||
|
# define UART7_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART7_USED && defined(UART7_RX_PIN)
|
||||||
|
# warning "UART7_RX_PIN is defined but UART7 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART7_USED && defined(UART7_RX_PIN)
|
||||||
|
# undef UART7_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART7_USED && !defined(UART7_TX_PIN)
|
||||||
|
# define UART7_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART7_USED && defined(UART7_TX_PIN)
|
||||||
|
# warning "UART7_TX_PIN is defined but UART7 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART7_USED && defined(UART7_TX_PIN)
|
||||||
|
# undef UART7_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART7_USED && !defined(INVERTER_PIN_UART7)
|
||||||
|
# define INVERTER_PIN_UART7 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART7_USED && defined(INVERTER_PIN_UART7)
|
||||||
|
# warning "INVERTER_PIN_UART7 is defined but UART7 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART7_USED && defined(INVERTER_PIN_UART7)
|
||||||
|
# undef INVERTER_PIN_UART7
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART8_USED && !defined(UART8_RX_PIN)
|
||||||
|
# define UART8_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART8_USED && defined(UART8_RX_PIN)
|
||||||
|
# warning "UART8_RX_PIN is defined but UART8 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART8_USED && defined(UART8_RX_PIN)
|
||||||
|
# undef UART8_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART8_USED && !defined(UART8_TX_PIN)
|
||||||
|
# define UART8_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART8_USED && defined(UART8_TX_PIN)
|
||||||
|
# warning "UART8_TX_PIN is defined but UART8 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART8_USED && defined(UART8_TX_PIN)
|
||||||
|
# undef UART8_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART8_USED && !defined(INVERTER_PIN_UART8)
|
||||||
|
# define INVERTER_PIN_UART8 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART8_USED && defined(INVERTER_PIN_UART8)
|
||||||
|
# warning "INVERTER_PIN_UART8 is defined but UART8 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART8_USED && defined(INVERTER_PIN_UART8)
|
||||||
|
# undef INVERTER_PIN_UART8
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART9_USED && !defined(UART9_RX_PIN)
|
||||||
|
# define UART9_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART9_USED && defined(UART9_RX_PIN)
|
||||||
|
# warning "UART9_RX_PIN is defined but UART9 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART9_USED && defined(UART9_RX_PIN)
|
||||||
|
# undef UART9_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART9_USED && !defined(UART9_TX_PIN)
|
||||||
|
# define UART9_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART9_USED && defined(UART9_TX_PIN)
|
||||||
|
# warning "UART9_TX_PIN is defined but UART9 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART9_USED && defined(UART9_TX_PIN)
|
||||||
|
# undef UART9_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART9_USED && !defined(INVERTER_PIN_UART9)
|
||||||
|
# define INVERTER_PIN_UART9 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART9_USED && defined(INVERTER_PIN_UART9)
|
||||||
|
# warning "INVERTER_PIN_UART9 is defined but UART9 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART9_USED && defined(INVERTER_PIN_UART9)
|
||||||
|
# undef INVERTER_PIN_UART9
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART10_USED && !defined(UART10_RX_PIN)
|
||||||
|
# define UART10_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART10_USED && defined(UART10_RX_PIN)
|
||||||
|
# warning "UART10_RX_PIN is defined but UART10 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART10_USED && defined(UART10_RX_PIN)
|
||||||
|
# undef UART10_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART10_USED && !defined(UART10_TX_PIN)
|
||||||
|
# define UART10_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART10_USED && defined(UART10_TX_PIN)
|
||||||
|
# warning "UART10_TX_PIN is defined but UART10 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART10_USED && defined(UART10_TX_PIN)
|
||||||
|
# undef UART10_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_UART10_USED && !defined(INVERTER_PIN_UART10)
|
||||||
|
# define INVERTER_PIN_UART10 NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART10_USED && defined(INVERTER_PIN_UART10)
|
||||||
|
# warning "INVERTER_PIN_UART10 is defined but UART10 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_UART10_USED && defined(INVERTER_PIN_UART10)
|
||||||
|
# undef INVERTER_PIN_UART10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**** LPUART *****/
|
||||||
|
|
||||||
|
#if defined(USE_LPUART1)
|
||||||
|
# define SERIAL_LPUART1_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_LPUART1_USED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SERIAL_LPUART_MASK ((SERIAL_LPUART1_USED * BIT(1 - 1)))
|
||||||
|
#define SERIAL_LPUART_COUNT (SERIAL_LPUART1_USED)
|
||||||
|
// 0 if no port is defined
|
||||||
|
#define SERIAL_LPUART_MAX (SERIAL_LPUART_MASK ? LOG2(SERIAL_LPUART_MASK) + 1 : 0)
|
||||||
|
|
||||||
|
|
||||||
|
// Normalize LPUART TX/RX
|
||||||
|
#if SERIAL_LPUART1_USED && !defined(LPUART1_RX_PIN)
|
||||||
|
# define LPUART1_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_LPUART1_USED && defined(LPUART1_RX_PIN)
|
||||||
|
# warning "LPUART1_RX_PIN is defined but LPUART1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_LPUART1_USED && defined(LPUART1_RX_PIN)
|
||||||
|
# undef LPUART1_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_LPUART1_USED && !defined(LPUART1_TX_PIN)
|
||||||
|
# define LPUART1_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_LPUART1_USED && defined(LPUART1_TX_PIN)
|
||||||
|
# warning "LPUART1_TX_PIN is defined but LPUART1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_LPUART1_USED && defined(LPUART1_TX_PIN)
|
||||||
|
# undef LPUART1_TX_PIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**** SOFTSERIAL *****/
|
||||||
|
#if defined(USE_SOFTSERIAL)
|
||||||
|
# if !defined(USE_SOFTSERIAL1)
|
||||||
|
# define USE_SOFTSERIAL1
|
||||||
|
# endif
|
||||||
|
# if !defined(USE_SOFTSERIAL2)
|
||||||
|
# define USE_SOFTSERIAL2
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_SOFTSERIAL1)
|
||||||
|
# define SERIAL_SOFTSERIAL1_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_SOFTSERIAL1_USED 0
|
||||||
|
#endif
|
||||||
|
#if defined(USE_SOFTSERIAL2)
|
||||||
|
# define SERIAL_SOFTSERIAL2_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_SOFTSERIAL2_USED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SERIAL_SOFTSERIAL_MASK ((SERIAL_SOFTSERIAL1_USED * BIT(1 - 1)) | (SERIAL_SOFTSERIAL2_USED * BIT(2 - 1)))
|
||||||
|
#define SERIAL_SOFTSERIAL_COUNT (SERIAL_SOFTSERIAL1_USED + SERIAL_SOFTSERIAL2_USED)
|
||||||
|
// 0 if no port is defined
|
||||||
|
#define SERIAL_SOFTSERIAL_MAX (SERIAL_SOFTSERIAL_MASK ? LOG2(SERIAL_SOFTSERIAL_MASK) + 1 : 0)
|
||||||
|
|
||||||
|
#if SERIAL_SOFTSERIAL_COUNT != SERIAL_SOFTSERIAL_MAX
|
||||||
|
# error SOFTSERIAL ports must start with SOFTSERIAL1 and be continuous
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Normalize SOFTSERIAL TX/RX
|
||||||
|
#if SERIAL_SOFTSERIAL1_USED && !defined(SOFTSERIAL1_RX_PIN)
|
||||||
|
# define SOFTSERIAL1_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_SOFTSERIAL1_USED && defined(SOFTSERIAL1_RX_PIN)
|
||||||
|
# warning "SOFTSERIAL1_RX_PIN is defined but SOFTSERIAL1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_SOFTSERIAL1_USED && defined(SOFTSERIAL1_RX_PIN)
|
||||||
|
# undef SOFTSERIAL1_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_SOFTSERIAL1_USED && !defined(SOFTSERIAL1_TX_PIN)
|
||||||
|
# define SOFTSERIAL1_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_SOFTSERIAL1_USED && defined(SOFTSERIAL1_TX_PIN)
|
||||||
|
# warning "SOFTSERIAL1_TX_PIN is defined but SOFTSERIAL1 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_SOFTSERIAL1_USED && defined(SOFTSERIAL1_TX_PIN)
|
||||||
|
# undef SOFTSERIAL1_TX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_SOFTSERIAL2_USED && !defined(SOFTSERIAL2_RX_PIN)
|
||||||
|
# define SOFTSERIAL2_RX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_SOFTSERIAL2_USED && defined(SOFTSERIAL2_RX_PIN)
|
||||||
|
# warning "SOFTSERIAL2_RX_PIN is defined but SOFTSERIAL2 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_SOFTSERIAL2_USED && defined(SOFTSERIAL2_RX_PIN)
|
||||||
|
# undef SOFTSERIAL2_RX_PIN
|
||||||
|
#endif
|
||||||
|
#if SERIAL_SOFTSERIAL2_USED && !defined(SOFTSERIAL2_TX_PIN)
|
||||||
|
# define SOFTSERIAL2_TX_PIN NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_SOFTSERIAL2_USED && defined(SOFTSERIAL2_TX_PIN)
|
||||||
|
# warning "SOFTSERIAL2_TX_PIN is defined but SOFTSERIAL2 is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_SOFTSERIAL2_USED && defined(SOFTSERIAL2_TX_PIN)
|
||||||
|
# undef SOFTSERIAL2_TX_PIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**** VCP *****/
|
||||||
|
|
||||||
|
#if defined(USE_VCP)
|
||||||
|
# define SERIAL_VCP_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_VCP_USED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set one bit if port is enabled for consistency
|
||||||
|
#define SERIAL_VCP_MASK (SERIAL_VCP_USED * BIT(0))
|
||||||
|
#define SERIAL_VCP_COUNT (SERIAL_VCP_USED)
|
||||||
|
// 0 if no port is defined
|
||||||
|
#define SERIAL_VCP_MAX (SERIAL_VCP_MASK ? LOG2(SERIAL_VCP_MASK) + 1 : 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// normalize USE_x after all ports are enumerated (x_COUNT of dependencies must be available)
|
||||||
|
#if !defined(USE_UART) && (SERIAL_UART_COUNT || SERIAL_LPUART_COUNT)
|
||||||
|
# define USE_UART
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_LPUART) && (SERIAL_LPUART_COUNT)
|
||||||
|
# define USE_LPUART
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_SOFTSERIAL) && (SERIAL_SOFTSERIAL_COUNT)
|
||||||
|
# define USE_SOFTSERIAL
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_VCP) && (SERIAL_VCP_COUNT)
|
||||||
|
# define USE_VCP
|
||||||
|
#endif
|
||||||
|
|
|
@ -372,13 +372,13 @@ static void workAroundForHottTelemetryOnUsart(serialPort_t *instance, portMode_e
|
||||||
if (telemetryConfig()->halfDuplex) {
|
if (telemetryConfig()->halfDuplex) {
|
||||||
portOptions |= SERIAL_BIDIR;
|
portOptions |= SERIAL_BIDIR;
|
||||||
}
|
}
|
||||||
|
// TODO - identifier is set only after opening port
|
||||||
hottPort = openSerialPort(instance->identifier, FUNCTION_TELEMETRY_HOTT, NULL, NULL, HOTT_BAUDRATE, mode, portOptions);
|
hottPort = openSerialPort(instance->identifier, FUNCTION_TELEMETRY_HOTT, NULL, NULL, HOTT_BAUDRATE, mode, portOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hottIsUsingHardwareUART(void)
|
static bool hottIsUsingHardwareUART(void)
|
||||||
{
|
{
|
||||||
return !(portConfig->identifier == SERIAL_PORT_SOFTSERIAL1 || portConfig->identifier == SERIAL_PORT_SOFTSERIAL2);
|
return serialType(portConfig->identifier) != SERIALTYPE_SOFTSERIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hottConfigurePortForTX(void)
|
static void hottConfigurePortForTX(void)
|
||||||
|
|
|
@ -487,7 +487,9 @@ static void freeSmartPortTelemetryPort(void)
|
||||||
static void configureSmartPortTelemetryPort(void)
|
static void configureSmartPortTelemetryPort(void)
|
||||||
{
|
{
|
||||||
if (portConfig) {
|
if (portConfig) {
|
||||||
portOptions_e portOptions = (telemetryConfig()->halfDuplex ? SERIAL_BIDIR : SERIAL_UNIDIR) | (telemetryConfig()->telemetry_inverted ? SERIAL_NOT_INVERTED : SERIAL_INVERTED);
|
// On SmartPort, SERIAL_INVERTED is default
|
||||||
|
const portOptions_e portOptions = (telemetryConfig()->halfDuplex ? SERIAL_BIDIR : 0)
|
||||||
|
| (telemetryConfig()->telemetry_inverted ? SERIAL_NOT_INVERTED : SERIAL_INVERTED);
|
||||||
|
|
||||||
smartPortSerialPort = openSerialPort(portConfig->identifier, FUNCTION_TELEMETRY_SMARTPORT, NULL, NULL, SMARTPORT_BAUD, SMARTPORT_UART_MODE, portOptions);
|
smartPortSerialPort = openSerialPort(portConfig->identifier, FUNCTION_TELEMETRY_SMARTPORT, NULL, NULL, SMARTPORT_BAUD, SMARTPORT_UART_MODE, portOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "drivers/dma_reqmap.h"
|
#include "drivers/dma_reqmap.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
#include "pg/timerio.h"
|
#include "pg/timerio.h"
|
||||||
|
|
||||||
|
@ -69,20 +70,30 @@ static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
|
||||||
{ DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
|
{ DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
|
||||||
#endif // USE_SDCARD_SDIO
|
#endif // USE_SDCARD_SDIO
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART1
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(2, 7, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(2, 7, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(2, 5, 4), DMA(2, 2, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(2, 5, 4), DMA(2, 2, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 6, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 6, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 5, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 5, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 3, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 3, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 1, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 1, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(1, 4, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(1, 4, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(1, 2, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(1, 2, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_5, { DMA(1, 7, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_5, { DMA(1, 7, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_5, { DMA(1, 0, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_5, { DMA(1, 0, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_6, { DMA(2, 6, 5), DMA(2, 7, 5) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_6, { DMA(2, 6, 5), DMA(2, 7, 5) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_6, { DMA(2, 1, 5), DMA(2, 2, 5) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_6, { DMA(2, 1, 5), DMA(2, 2, 5) } },
|
||||||
#endif // USE_UART
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
|
#define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
|
||||||
|
|
|
@ -24,46 +24,26 @@
|
||||||
* Dominic Clifton - Serial port abstraction, Separation of common STM32 code for cleanflight, various cleanups.
|
* Dominic Clifton - Serial port abstraction, Separation of common STM32 code for cleanflight, various cleanups.
|
||||||
* Hamasaki/Timecop - Initial baseflight code
|
* Hamasaki/Timecop - Initial baseflight code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include "build/debug.h"
|
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART
|
||||||
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "build/atomic.h"
|
#include "build/atomic.h"
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
#include "drivers/io.h"
|
|
||||||
#include "drivers/nvic.h"
|
|
||||||
#include "drivers/inverter.h"
|
#include "drivers/inverter.h"
|
||||||
#include "drivers/dma.h"
|
#include "drivers/nvic.h"
|
||||||
#include "drivers/rcc.h"
|
#include "drivers/rcc.h"
|
||||||
|
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
static void usartConfigurePinInversion(uartPort_t *uartPort)
|
|
||||||
{
|
|
||||||
#if !defined(USE_INVERTER)
|
|
||||||
UNUSED(uartPort);
|
|
||||||
#else
|
|
||||||
bool inverted = uartPort->port.options & SERIAL_INVERTED;
|
|
||||||
|
|
||||||
#ifdef USE_INVERTER
|
|
||||||
if (inverted) {
|
|
||||||
// Enable hardware inverter if available.
|
|
||||||
enableInverter(uartPort->USARTx, true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX uartReconfigure does not handle resource management properly.
|
// XXX uartReconfigure does not handle resource management properly.
|
||||||
|
|
||||||
void uartReconfigure(uartPort_t *uartPort)
|
void uartReconfigure(uartPort_t *uartPort)
|
||||||
|
@ -84,29 +64,25 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
if (uartPort->port.mode & MODE_TX)
|
if (uartPort->port.mode & MODE_TX)
|
||||||
uartPort->Handle.Init.Mode |= UART_MODE_TX;
|
uartPort->Handle.Init.Mode |= UART_MODE_TX;
|
||||||
|
|
||||||
|
// config external pin inverter (no internal pin inversion available)
|
||||||
usartConfigurePinInversion(uartPort);
|
uartConfigureExternalPinInversion(uartPort);
|
||||||
|
|
||||||
#ifdef TARGET_USART_CONFIG
|
#ifdef TARGET_USART_CONFIG
|
||||||
|
// TODO: move declaration into header file
|
||||||
void usartTargetConfigure(uartPort_t *);
|
void usartTargetConfigure(uartPort_t *);
|
||||||
usartTargetConfigure(uartPort);
|
usartTargetConfigure(uartPort);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (uartPort->port.options & SERIAL_BIDIR)
|
if (uartPort->port.options & SERIAL_BIDIR) {
|
||||||
{
|
|
||||||
DAL_HalfDuplex_Init(&uartPort->Handle);
|
DAL_HalfDuplex_Init(&uartPort->Handle);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
DAL_UART_Init(&uartPort->Handle);
|
DAL_UART_Init(&uartPort->Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive DMA or IRQ
|
// Receive DMA or IRQ
|
||||||
if (uartPort->port.mode & MODE_RX)
|
if (uartPort->port.mode & MODE_RX) {
|
||||||
{
|
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
if (uartPort->rxDMAResource)
|
if (uartPort->rxDMAResource) {
|
||||||
{
|
|
||||||
uartPort->rxDMAHandle.Instance = (DMA_ARCH_TYPE *)uartPort->rxDMAResource;
|
uartPort->rxDMAHandle.Instance = (DMA_ARCH_TYPE *)uartPort->rxDMAResource;
|
||||||
uartPort->txDMAHandle.Init.Channel = uartPort->rxDMAChannel;
|
uartPort->txDMAHandle.Init.Channel = uartPort->rxDMAChannel;
|
||||||
uartPort->rxDMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
uartPort->rxDMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||||
|
@ -170,8 +146,7 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
|
|
||||||
DAL_DMA_DeInit(&uartPort->txDMAHandle);
|
DAL_DMA_DeInit(&uartPort->txDMAHandle);
|
||||||
DAL_StatusTypeDef status = DAL_DMA_Init(&uartPort->txDMAHandle);
|
DAL_StatusTypeDef status = DAL_DMA_Init(&uartPort->txDMAHandle);
|
||||||
if (status != DAL_OK)
|
if (status != DAL_OK) {
|
||||||
{
|
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
/* Associate the initialized DMA handle to the UART handle */
|
/* Associate the initialized DMA handle to the UART handle */
|
||||||
|
@ -187,55 +162,14 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
SET_BIT(uartPort->USARTx->CTRL1, USART_CTRL1_TXCIEN);
|
SET_BIT(uartPort->USARTx->CTRL1, USART_CTRL1_TXCIEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkUsartTxOutput(uartPort_t *s)
|
|
||||||
{
|
|
||||||
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
|
||||||
IO_t txIO = IOGetByTag(uart->tx.pin);
|
|
||||||
|
|
||||||
if ((uart->txPinState == TX_PIN_MONITOR) && txIO) {
|
|
||||||
if (IORead(txIO)) {
|
|
||||||
// TX is high so we're good to transmit
|
|
||||||
|
|
||||||
// Enable USART TX output
|
|
||||||
uart->txPinState = TX_PIN_ACTIVE;
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uart->tx.af);
|
|
||||||
|
|
||||||
// Enable the UART transmitter
|
|
||||||
SET_BIT(s->Handle.Instance->CTRL1, USART_CTRL1_TXEN);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// TX line is pulled low so don't enable USART TX
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartTxMonitor(uartPort_t *s)
|
|
||||||
{
|
|
||||||
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
|
||||||
|
|
||||||
if (uart->txPinState == TX_PIN_ACTIVE) {
|
|
||||||
IO_t txIO = IOGetByTag(uart->tx.pin);
|
|
||||||
|
|
||||||
// Disable the UART transmitter
|
|
||||||
CLEAR_BIT(s->Handle.Instance->CTRL1, USART_CTRL1_TXEN);
|
|
||||||
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uart->txPinState = TX_PIN_MONITOR;
|
|
||||||
IOConfigGPIO(txIO, IOCFG_IPU);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
|
|
||||||
void uartTryStartTxDMA(uartPort_t *s)
|
void uartTryStartTxDMA(uartPort_t *s)
|
||||||
{
|
{
|
||||||
|
// uartTryStartTxDMA must be protected, since it is called from
|
||||||
|
// uartWrite and handleUsartTxDma (an ISR).
|
||||||
|
|
||||||
ATOMIC_BLOCK(NVIC_PRIO_SERIALUART_TXDMA) {
|
ATOMIC_BLOCK(NVIC_PRIO_SERIALUART_TXDMA) {
|
||||||
if (IS_DMA_ENABLED(s->txDMAResource)) {
|
if (IS_DMA_ENABLED(s->txDMAResource)) {
|
||||||
// DMA is already in progress
|
// DMA is already in progress
|
||||||
|
@ -254,106 +188,19 @@ void uartTryStartTxDMA(uartPort_t *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t size;
|
unsigned chunk;
|
||||||
uint32_t fromwhere = s->port.txBufferTail;
|
uint32_t fromwhere = s->port.txBufferTail;
|
||||||
|
|
||||||
if (s->port.txBufferHead > s->port.txBufferTail) {
|
if (s->port.txBufferHead > s->port.txBufferTail) {
|
||||||
size = s->port.txBufferHead - s->port.txBufferTail;
|
chunk = s->port.txBufferHead - s->port.txBufferTail;
|
||||||
s->port.txBufferTail = s->port.txBufferHead;
|
s->port.txBufferTail = s->port.txBufferHead;
|
||||||
} else {
|
} else {
|
||||||
size = s->port.txBufferSize - s->port.txBufferTail;
|
chunk = s->port.txBufferSize - s->port.txBufferTail;
|
||||||
s->port.txBufferTail = 0;
|
s->port.txBufferTail = 0;
|
||||||
}
|
}
|
||||||
s->txDMAEmpty = false;
|
s->txDMAEmpty = false;
|
||||||
|
DAL_UART_Transmit_DMA(&s->Handle, (uint8_t*)s->port.txBuffer + fromwhere, chunk);
|
||||||
DAL_UART_Transmit_DMA(&s->Handle, (uint8_t *)&s->port.txBuffer[fromwhere], size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
static void handleUsartTxDma(uartPort_t *s)
|
|
||||||
{
|
|
||||||
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
|
||||||
|
|
||||||
uartTryStartTxDMA(s);
|
|
||||||
|
|
||||||
if (s->txDMAEmpty && (uart->txPinState != TX_PIN_IGNORE)) {
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor)
|
|
||||||
{
|
|
||||||
UNUSED(descriptor);
|
|
||||||
uartPort_t *s = &(((uartDevice_t*)(descriptor->userParam))->port);
|
|
||||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF))
|
|
||||||
{
|
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_HTIF);
|
|
||||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_FEIF))
|
|
||||||
{
|
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_FEIF);
|
|
||||||
}
|
|
||||||
handleUsartTxDma(s);
|
|
||||||
}
|
|
||||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TEIF))
|
|
||||||
{
|
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TEIF);
|
|
||||||
}
|
|
||||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_DMEIF))
|
|
||||||
{
|
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_DMEIF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // USE_DMA
|
|
||||||
|
|
||||||
FAST_IRQ_HANDLER void uartIrqHandler(uartPort_t *s)
|
|
||||||
{
|
|
||||||
UART_HandleTypeDef *huart = &s->Handle;
|
|
||||||
uint32_t isrflags = READ_REG(huart->Instance->STS);
|
|
||||||
uint32_t cr1its = READ_REG(huart->Instance->CTRL1);
|
|
||||||
uint32_t cr3its = READ_REG(huart->Instance->CTRL3);
|
|
||||||
/* UART in mode Receiver ---------------------------------------------------*/
|
|
||||||
if (!s->rxDMAResource && (((isrflags & USART_STS_RXBNEFLG) != RESET) && ((cr1its & USART_CTRL1_RXBNEIEN) != RESET))) {
|
|
||||||
if (s->port.rxCallback) {
|
|
||||||
s->port.rxCallback(huart->Instance->DATA, s->port.rxCallbackData);
|
|
||||||
} else {
|
|
||||||
s->port.rxBuffer[s->port.rxBufferHead] = huart->Instance->DATA;
|
|
||||||
s->port.rxBufferHead = (s->port.rxBufferHead + 1) % s->port.rxBufferSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect completion of transmission
|
|
||||||
if (((isrflags & USART_STS_TXCFLG) != RESET) && ((cr1its & USART_CTRL1_TXCIEN) != RESET)) {
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
|
|
||||||
__DAL_UART_CLEAR_FLAG(huart, UART_IT_TC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!s->txDMAResource && (((isrflags & USART_STS_TXBEFLG) != RESET) && ((cr1its & USART_CTRL1_TXBEIEN) != RESET))) {
|
|
||||||
if (s->port.txBufferTail != s->port.txBufferHead) {
|
|
||||||
huart->Instance->DATA = (((uint16_t) s->port.txBuffer[s->port.txBufferTail]) & (uint16_t) 0x01FFU);
|
|
||||||
s->port.txBufferTail = (s->port.txBufferTail + 1) % s->port.txBufferSize;
|
|
||||||
} else {
|
|
||||||
__DAL_UART_DISABLE_IT(huart, UART_IT_TXE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((isrflags & USART_STS_OVREFLG) != RESET) && (((cr1its & USART_CTRL1_RXBNEIEN) != RESET)
|
|
||||||
|| ((cr3its & USART_CTRL3_ERRIEN) != RESET))) {
|
|
||||||
__DAL_UART_CLEAR_OREFLAG(huart);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((isrflags & USART_STS_IDLEFLG) != RESET) && ((cr1its & USART_STS_IDLEFLG) != RESET)) {
|
|
||||||
if (s->port.idleCallback) {
|
|
||||||
s->port.idleCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear
|
|
||||||
(void) huart->Instance->STS;
|
|
||||||
(void) huart->Instance->DATA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "build/debug.h"
|
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -55,13 +54,9 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1_TX_DMA
|
#ifdef USE_UART1_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA2_Stream7,
|
.txDMAResource = (dmaResource_t *)DMA2_Stream7,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PA10) }, { DEFIO_TAG_E(PB7) },
|
||||||
{ DEFIO_TAG_E(PA10), GPIO_AF7_USART1 },
|
|
||||||
{ DEFIO_TAG_E(PB7), GPIO_AF7_USART1 },
|
|
||||||
},
|
},
|
||||||
.txPins = {
|
.txPins = { { DEFIO_TAG_E(PA9) }, { DEFIO_TAG_E(PB6) },
|
||||||
{ DEFIO_TAG_E(PA9), GPIO_AF7_USART1 },
|
|
||||||
{ DEFIO_TAG_E(PB6), GPIO_AF7_USART1 },
|
|
||||||
},
|
},
|
||||||
.af = GPIO_AF7_USART1,
|
.af = GPIO_AF7_USART1,
|
||||||
.rcc = RCC_APB2(USART1),
|
.rcc = RCC_APB2(USART1),
|
||||||
|
@ -77,7 +72,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -87,14 +82,8 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART2_TX_DMA
|
#ifdef USE_UART2_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA1_Stream6,
|
.txDMAResource = (dmaResource_t *)DMA1_Stream6,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PA3) }, { DEFIO_TAG_E(PD6) } },
|
||||||
{ DEFIO_TAG_E(PA3), GPIO_AF7_USART2 },
|
.txPins = { { DEFIO_TAG_E(PA2) }, { DEFIO_TAG_E(PD5) } },
|
||||||
{ DEFIO_TAG_E(PD6), GPIO_AF7_USART2 }
|
|
||||||
},
|
|
||||||
.txPins = {
|
|
||||||
{ DEFIO_TAG_E(PA2), GPIO_AF7_USART2 },
|
|
||||||
{ DEFIO_TAG_E(PD5), GPIO_AF7_USART2 }
|
|
||||||
},
|
|
||||||
.af = GPIO_AF7_USART2,
|
.af = GPIO_AF7_USART2,
|
||||||
.rcc = RCC_APB1(USART2),
|
.rcc = RCC_APB1(USART2),
|
||||||
.irqn = USART2_IRQn,
|
.irqn = USART2_IRQn,
|
||||||
|
@ -109,7 +98,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -119,16 +108,8 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART3_TX_DMA
|
#ifdef USE_UART3_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA1_Stream3,
|
.txDMAResource = (dmaResource_t *)DMA1_Stream3,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PB11) }, { DEFIO_TAG_E(PC11) }, { DEFIO_TAG_E(PD9) } },
|
||||||
{ DEFIO_TAG_E(PB11), GPIO_AF7_USART3 },
|
.txPins = { { DEFIO_TAG_E(PB10) }, { DEFIO_TAG_E(PC10) }, { DEFIO_TAG_E(PD8) } },
|
||||||
{ DEFIO_TAG_E(PC11), GPIO_AF7_USART3 },
|
|
||||||
{ DEFIO_TAG_E(PD9), GPIO_AF7_USART3 }
|
|
||||||
},
|
|
||||||
.txPins = {
|
|
||||||
{ DEFIO_TAG_E(PB10), GPIO_AF7_USART3 },
|
|
||||||
{ DEFIO_TAG_E(PC10), GPIO_AF7_USART3 },
|
|
||||||
{ DEFIO_TAG_E(PD8), GPIO_AF7_USART3 }
|
|
||||||
},
|
|
||||||
.af = GPIO_AF7_USART3,
|
.af = GPIO_AF7_USART3,
|
||||||
.rcc = RCC_APB1(USART3),
|
.rcc = RCC_APB1(USART3),
|
||||||
.irqn = USART3_IRQn,
|
.irqn = USART3_IRQn,
|
||||||
|
@ -143,7 +124,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -153,14 +134,8 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART4_TX_DMA
|
#ifdef USE_UART4_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA1_Stream4,
|
.txDMAResource = (dmaResource_t *)DMA1_Stream4,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PA1) }, { DEFIO_TAG_E(PC11) } },
|
||||||
{ DEFIO_TAG_E(PA1), GPIO_AF8_UART4 },
|
.txPins = { { DEFIO_TAG_E(PA0) }, { DEFIO_TAG_E(PC10) } },
|
||||||
{ DEFIO_TAG_E(PC11), GPIO_AF8_UART4 }
|
|
||||||
},
|
|
||||||
.txPins = {
|
|
||||||
{ DEFIO_TAG_E(PA0), GPIO_AF8_UART4 },
|
|
||||||
{ DEFIO_TAG_E(PC10), GPIO_AF8_UART4 }
|
|
||||||
},
|
|
||||||
.af = GPIO_AF8_UART4,
|
.af = GPIO_AF8_UART4,
|
||||||
.rcc = RCC_APB1(UART4),
|
.rcc = RCC_APB1(UART4),
|
||||||
.irqn = UART4_IRQn,
|
.irqn = UART4_IRQn,
|
||||||
|
@ -175,7 +150,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -185,12 +160,8 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART5_TX_DMA
|
#ifdef USE_UART5_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA1_Stream7,
|
.txDMAResource = (dmaResource_t *)DMA1_Stream7,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PD2) } },
|
||||||
{ DEFIO_TAG_E(PD2), GPIO_AF8_UART5 }
|
.txPins = { { DEFIO_TAG_E(PC12) } },
|
||||||
},
|
|
||||||
.txPins = {
|
|
||||||
{ DEFIO_TAG_E(PC12), GPIO_AF8_UART5 }
|
|
||||||
},
|
|
||||||
.af = GPIO_AF8_UART5,
|
.af = GPIO_AF8_UART5,
|
||||||
.rcc = RCC_APB1(UART5),
|
.rcc = RCC_APB1(UART5),
|
||||||
.irqn = UART5_IRQn,
|
.irqn = UART5_IRQn,
|
||||||
|
@ -205,7 +176,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
{
|
{
|
||||||
.device = UARTDEV_6,
|
.identifier = SERIAL_PORT_USART6,
|
||||||
.reg = USART6,
|
.reg = USART6,
|
||||||
.rxDMAChannel = DMA_CHANNEL_5,
|
.rxDMAChannel = DMA_CHANNEL_5,
|
||||||
.txDMAChannel = DMA_CHANNEL_5,
|
.txDMAChannel = DMA_CHANNEL_5,
|
||||||
|
@ -215,14 +186,8 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART6_TX_DMA
|
#ifdef USE_UART6_TX_DMA
|
||||||
.txDMAResource = (dmaResource_t *)DMA2_Stream6,
|
.txDMAResource = (dmaResource_t *)DMA2_Stream6,
|
||||||
#endif
|
#endif
|
||||||
.rxPins = {
|
.rxPins = { { DEFIO_TAG_E(PC7) }, { DEFIO_TAG_E(PG9) } },
|
||||||
{ DEFIO_TAG_E(PC7), GPIO_AF8_USART6 },
|
.txPins = { { DEFIO_TAG_E(PC6) }, { DEFIO_TAG_E(PG14) } },
|
||||||
{ DEFIO_TAG_E(PG9), GPIO_AF8_USART6 }
|
|
||||||
},
|
|
||||||
.txPins = {
|
|
||||||
{ DEFIO_TAG_E(PC6), GPIO_AF8_USART6 },
|
|
||||||
{ DEFIO_TAG_E(PG14), GPIO_AF8_USART6 }
|
|
||||||
},
|
|
||||||
.af = GPIO_AF8_USART6,
|
.af = GPIO_AF8_USART6,
|
||||||
.rcc = RCC_APB2(USART6),
|
.rcc = RCC_APB2(USART6),
|
||||||
.irqn = USART6_IRQn,
|
.irqn = USART6_IRQn,
|
||||||
|
@ -236,83 +201,130 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX Should serialUART be consolidated?
|
bool checkUsartTxOutput(uartPort_t *s)
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
{
|
||||||
uartDevice_t *uartdev = uartDevmap[device];
|
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
||||||
if (!uartdev) {
|
IO_t txIO = IOGetByTag(uart->tx.pin);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uartPort_t *s = &(uartdev->port);
|
if ((uart->txPinState == TX_PIN_MONITOR) && txIO) {
|
||||||
|
if (IORead(txIO)) {
|
||||||
|
// TX is high so we're good to transmit
|
||||||
|
|
||||||
s->port.vTable = uartVTable;
|
// Enable USART TX output
|
||||||
|
uart->txPinState = TX_PIN_ACTIVE;
|
||||||
|
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uart->hardware->af);
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
// Enable the UART transmitter
|
||||||
|
SET_BIT(s->Handle.Instance->CTRL1, USART_CTRL1_TXEN);
|
||||||
|
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
return true;
|
||||||
|
} else {
|
||||||
s->USARTx = hardware->reg;
|
// TX line is pulled low so don't enable USART TX
|
||||||
|
return false;
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uartdev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->Handle.Instance = hardware->reg;
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
|
||||||
|
|
||||||
uartdev->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if ((options & SERIAL_BIDIR) && txIO) {
|
|
||||||
ioConfig_t ioCfg = IO_CONFIG(
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
|
|
||||||
GPIO_SPEED_FREQ_HIGH,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULLDOWN : GPIO_PULLUP
|
|
||||||
);
|
|
||||||
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (options & SERIAL_CHECK_TX) {
|
|
||||||
uartdev->txPinState = TX_PIN_MONITOR;
|
|
||||||
// Switch TX to UART output whilst UART sends idle preamble
|
|
||||||
checkUsartTxOutput(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DMA
|
return true;
|
||||||
if (!s->rxDMAResource) {
|
|
||||||
DAL_NVIC_SetPriority(hardware->irqn, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
|
||||||
DAL_NVIC_EnableIRQ(hardware->irqn);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uartTxMonitor(uartPort_t *s)
|
||||||
|
{
|
||||||
|
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
||||||
|
|
||||||
|
if (uart->txPinState == TX_PIN_ACTIVE) {
|
||||||
|
IO_t txIO = IOGetByTag(uart->tx.pin);
|
||||||
|
|
||||||
|
// Disable the UART transmitter
|
||||||
|
CLEAR_BIT(s->Handle.Instance->CTRL1, USART_CTRL1_TXEN);
|
||||||
|
|
||||||
|
// Switch TX to an input with pullup so it's state can be monitored
|
||||||
|
uart->txPinState = TX_PIN_MONITOR;
|
||||||
|
IOConfigGPIO(txIO, IOCFG_IPU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleUsartTxDma(uartPort_t *s)
|
||||||
|
{
|
||||||
|
uartDevice_t *uart = container_of(s, uartDevice_t, port);
|
||||||
|
|
||||||
|
uartTryStartTxDMA(s);
|
||||||
|
|
||||||
|
if (s->txDMAEmpty && (uart->txPinState != TX_PIN_IGNORE)) {
|
||||||
|
// Switch TX to an input with pullup so it's state can be monitored
|
||||||
|
uartTxMonitor(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor)
|
||||||
|
{
|
||||||
|
uartPort_t *s = &(((uartDevice_t*)(descriptor->userParam))->port);
|
||||||
|
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF))
|
||||||
|
{
|
||||||
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
||||||
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_HTIF);
|
||||||
|
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_FEIF))
|
||||||
|
{
|
||||||
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_FEIF);
|
||||||
|
}
|
||||||
|
handleUsartTxDma(s);
|
||||||
|
}
|
||||||
|
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TEIF))
|
||||||
|
{
|
||||||
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_TEIF);
|
||||||
|
}
|
||||||
|
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_DMEIF))
|
||||||
|
{
|
||||||
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_DMEIF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FAST_IRQ_HANDLER void uartIrqHandler(uartPort_t *s)
|
||||||
|
{
|
||||||
|
UART_HandleTypeDef *huart = &s->Handle;
|
||||||
|
uint32_t isrflags = READ_REG(huart->Instance->STS);
|
||||||
|
uint32_t cr1its = READ_REG(huart->Instance->CTRL1);
|
||||||
|
uint32_t cr3its = READ_REG(huart->Instance->CTRL3);
|
||||||
|
/* UART in mode Receiver ---------------------------------------------------*/
|
||||||
|
if (!s->rxDMAResource && (((isrflags & USART_STS_RXBNEFLG) != RESET) && ((cr1its & USART_CTRL1_RXBNEIEN) != RESET))) {
|
||||||
|
if (s->port.rxCallback) {
|
||||||
|
s->port.rxCallback(huart->Instance->DATA, s->port.rxCallbackData);
|
||||||
|
} else {
|
||||||
|
s->port.rxBuffer[s->port.rxBufferHead] = huart->Instance->DATA;
|
||||||
|
s->port.rxBufferHead = (s->port.rxBufferHead + 1) % s->port.rxBufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect completion of transmission
|
||||||
|
if (((isrflags & USART_STS_TXCFLG) != RESET) && ((cr1its & USART_CTRL1_TXCIEN) != RESET)) {
|
||||||
|
// Switch TX to an input with pullup so it's state can be monitored
|
||||||
|
uartTxMonitor(s);
|
||||||
|
|
||||||
|
__DAL_UART_CLEAR_FLAG(huart, UART_IT_TC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->txDMAResource && (((isrflags & USART_STS_TXBEFLG) != RESET) && ((cr1its & USART_CTRL1_TXBEIEN) != RESET))) {
|
||||||
|
if (s->port.txBufferTail != s->port.txBufferHead) {
|
||||||
|
huart->Instance->DATA = (((uint16_t) s->port.txBuffer[s->port.txBufferTail]) & (uint16_t) 0x01FFU);
|
||||||
|
s->port.txBufferTail = (s->port.txBufferTail + 1) % s->port.txBufferSize;
|
||||||
|
} else {
|
||||||
|
__DAL_UART_DISABLE_IT(huart, UART_IT_TXE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((isrflags & USART_STS_OVREFLG) != RESET) && (((cr1its & USART_CTRL1_RXBNEIEN) != RESET)
|
||||||
|
|| ((cr3its & USART_CTRL3_ERRIEN) != RESET))) {
|
||||||
|
__DAL_UART_CLEAR_OREFLAG(huart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((isrflags & USART_STS_IDLEFLG) != RESET) && ((cr1its & USART_STS_IDLEFLG) != RESET)) {
|
||||||
|
if (s->port.idleCallback) {
|
||||||
|
s->port.idleCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear
|
||||||
|
(void) huart->Instance->STS;
|
||||||
|
(void) huart->Instance->DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_UART6
|
#define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 6)
|
|
||||||
|
|
||||||
#define USE_INVERTER
|
#define USE_INVERTER
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_UART6
|
#define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 6)
|
|
||||||
|
|
||||||
#define USE_INVERTER
|
#define USE_INVERTER
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "drivers/dma_reqmap.h"
|
#include "drivers/dma_reqmap.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
|
#include "drivers/serial_uart_impl.h"
|
||||||
#include "pg/timerio.h"
|
#include "pg/timerio.h"
|
||||||
|
|
||||||
typedef struct dmaPeripheralMapping_s {
|
typedef struct dmaPeripheralMapping_s {
|
||||||
|
@ -97,17 +97,28 @@ static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
|
||||||
REQMAP(ADC, 3),
|
REQMAP(ADC, 3),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART
|
// UARTDEV_x enum value exists only when coresponding UART is enabled
|
||||||
|
#ifdef USE_UART1
|
||||||
REQMAP_DIR(UART, 1, TX),
|
REQMAP_DIR(UART, 1, TX),
|
||||||
REQMAP_DIR(UART, 1, RX),
|
REQMAP_DIR(UART, 1, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
REQMAP_DIR(UART, 2, TX),
|
REQMAP_DIR(UART, 2, TX),
|
||||||
REQMAP_DIR(UART, 2, RX),
|
REQMAP_DIR(UART, 2, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
REQMAP_DIR(UART, 3, TX),
|
REQMAP_DIR(UART, 3, TX),
|
||||||
REQMAP_DIR(UART, 3, RX),
|
REQMAP_DIR(UART, 3, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
REQMAP_DIR(UART, 4, TX),
|
REQMAP_DIR(UART, 4, TX),
|
||||||
REQMAP_DIR(UART, 4, RX),
|
REQMAP_DIR(UART, 4, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
REQMAP_DIR(UART, 5, TX),
|
REQMAP_DIR(UART, 5, TX),
|
||||||
REQMAP_DIR(UART, 5, RX),
|
REQMAP_DIR(UART, 5, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
REQMAP_DIR(UART, 6, TX),
|
REQMAP_DIR(UART, 6, TX),
|
||||||
REQMAP_DIR(UART, 6, RX),
|
REQMAP_DIR(UART, 6, RX),
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,40 +48,9 @@
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
static void usartConfigurePinInversion(uartPort_t *uartPort) {
|
|
||||||
#if !defined(USE_INVERTER) && !defined(STM32F303xC)
|
|
||||||
UNUSED(uartPort);
|
|
||||||
#else
|
|
||||||
bool inverted = uartPort->port.options & SERIAL_INVERTED;
|
|
||||||
|
|
||||||
#ifdef USE_INVERTER
|
|
||||||
if (inverted) {
|
|
||||||
// Enable hardware inverter if available.
|
|
||||||
enableInverter(uartPort->USARTx, TRUE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static uartDevice_t *uartFindDevice(uartPort_t *uartPort)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < UARTDEV_COUNT_MAX; i++) {
|
|
||||||
uartDevice_t *candidate = uartDevmap[i];
|
|
||||||
|
|
||||||
if (&candidate->port == uartPort) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uartConfigurePinSwap(uartPort_t *uartPort)
|
static void uartConfigurePinSwap(uartPort_t *uartPort)
|
||||||
{
|
{
|
||||||
uartDevice_t *uartDevice = uartFindDevice(uartPort);
|
uartDevice_t *uartDevice = container_of(uartPort, uartDevice_t, port);
|
||||||
if (!uartDevice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uartDevice->pinSwap) {
|
if (uartDevice->pinSwap) {
|
||||||
usart_transmit_receive_pin_swap(uartDevice->port.USARTx, TRUE);
|
usart_transmit_receive_pin_swap(uartDevice->port.USARTx, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -107,15 +76,15 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
if (uartPort->port.mode & MODE_RX) {
|
if (uartPort->port.mode & MODE_RX) {
|
||||||
usart_receiver_enable(uartPort->USARTx, TRUE);
|
usart_receiver_enable(uartPort->USARTx, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uartPort->port.mode & MODE_TX) {
|
if (uartPort->port.mode & MODE_TX) {
|
||||||
usart_transmitter_enable(uartPort->USARTx, TRUE);
|
usart_transmitter_enable(uartPort->USARTx, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//config pin inverter
|
// config external pin inverter (no internal pin inversion available)
|
||||||
usartConfigurePinInversion(uartPort);
|
uartConfigureExternalPinInversion(uartPort);
|
||||||
|
|
||||||
//config pin swap
|
// config pin swap
|
||||||
uartConfigurePinSwap(uartPort);
|
uartConfigurePinSwap(uartPort);
|
||||||
|
|
||||||
if (uartPort->port.options & SERIAL_BIDIR) {
|
if (uartPort->port.options & SERIAL_BIDIR) {
|
||||||
|
@ -132,16 +101,16 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
if (uartPort->rxDMAResource) {
|
if (uartPort->rxDMAResource) {
|
||||||
|
|
||||||
dma_default_para_init(&DMA_InitStructure);
|
dma_default_para_init(&DMA_InitStructure);
|
||||||
DMA_InitStructure.loop_mode_enable=TRUE;
|
DMA_InitStructure.loop_mode_enable = TRUE;
|
||||||
DMA_InitStructure.peripheral_base_addr=uartPort->rxDMAPeripheralBaseAddr;
|
DMA_InitStructure.peripheral_base_addr = uartPort->rxDMAPeripheralBaseAddr;
|
||||||
DMA_InitStructure.priority = DMA_PRIORITY_MEDIUM;
|
DMA_InitStructure.priority = DMA_PRIORITY_MEDIUM;
|
||||||
DMA_InitStructure.peripheral_inc_enable =FALSE;
|
DMA_InitStructure.peripheral_inc_enable = FALSE;
|
||||||
DMA_InitStructure.peripheral_data_width =DMA_PERIPHERAL_DATA_WIDTH_BYTE;
|
DMA_InitStructure.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
|
||||||
DMA_InitStructure.memory_inc_enable =TRUE;
|
DMA_InitStructure.memory_inc_enable = TRUE;
|
||||||
DMA_InitStructure.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
|
DMA_InitStructure.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
|
||||||
DMA_InitStructure.memory_base_addr=(uint32_t)uartPort->port.rxBuffer;
|
DMA_InitStructure.memory_base_addr = (uint32_t)uartPort->port.rxBuffer;
|
||||||
DMA_InitStructure.buffer_size = uartPort->port.rxBufferSize;
|
DMA_InitStructure.buffer_size = uartPort->port.rxBufferSize;
|
||||||
DMA_InitStructure.direction= DMA_DIR_PERIPHERAL_TO_MEMORY;
|
DMA_InitStructure.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
|
||||||
|
|
||||||
xDMA_DeInit(uartPort->rxDMAResource);
|
xDMA_DeInit(uartPort->rxDMAResource);
|
||||||
xDMA_Init(uartPort->rxDMAResource, &DMA_InitStructure);
|
xDMA_Init(uartPort->rxDMAResource, &DMA_InitStructure);
|
||||||
|
@ -159,16 +128,16 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
if (uartPort->port.mode & MODE_TX) {
|
if (uartPort->port.mode & MODE_TX) {
|
||||||
if (uartPort->txDMAResource) {
|
if (uartPort->txDMAResource) {
|
||||||
dma_default_para_init(&DMA_InitStructure);
|
dma_default_para_init(&DMA_InitStructure);
|
||||||
DMA_InitStructure.loop_mode_enable=FALSE;
|
DMA_InitStructure.loop_mode_enable = FALSE;
|
||||||
DMA_InitStructure.peripheral_base_addr=uartPort->txDMAPeripheralBaseAddr;
|
DMA_InitStructure.peripheral_base_addr = uartPort->txDMAPeripheralBaseAddr;
|
||||||
DMA_InitStructure.priority = DMA_PRIORITY_MEDIUM;
|
DMA_InitStructure.priority = DMA_PRIORITY_MEDIUM;
|
||||||
DMA_InitStructure.peripheral_inc_enable =FALSE;
|
DMA_InitStructure.peripheral_inc_enable = FALSE;
|
||||||
DMA_InitStructure.peripheral_data_width =DMA_PERIPHERAL_DATA_WIDTH_BYTE;
|
DMA_InitStructure.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
|
||||||
DMA_InitStructure.memory_inc_enable =TRUE;
|
DMA_InitStructure.memory_inc_enable = TRUE;
|
||||||
DMA_InitStructure.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
|
DMA_InitStructure.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
|
||||||
DMA_InitStructure.memory_base_addr=(uint32_t)uartPort->port.txBuffer;
|
DMA_InitStructure.memory_base_addr = (uint32_t)uartPort->port.txBuffer;
|
||||||
DMA_InitStructure.buffer_size = uartPort->port.txBufferSize;
|
DMA_InitStructure.buffer_size = uartPort->port.txBufferSize;
|
||||||
DMA_InitStructure.direction= DMA_DIR_MEMORY_TO_PERIPHERAL;
|
DMA_InitStructure.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
|
||||||
|
|
||||||
xDMA_DeInit(uartPort->txDMAResource);
|
xDMA_DeInit(uartPort->txDMAResource);
|
||||||
xDMA_Init(uartPort->txDMAResource, &DMA_InitStructure);
|
xDMA_Init(uartPort->txDMAResource, &DMA_InitStructure);
|
||||||
|
@ -181,7 +150,7 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
}
|
}
|
||||||
usart_interrupt_enable(uartPort->USARTx, USART_TDC_INT, TRUE);
|
usart_interrupt_enable(uartPort->USARTx, USART_TDC_INT, TRUE);
|
||||||
}
|
}
|
||||||
|
// TODO: usart_enable is called twice
|
||||||
usart_enable(uartPort->USARTx,TRUE);
|
usart_enable(uartPort->USARTx,TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +297,7 @@ void uartIrqHandler(uartPort_t *s)
|
||||||
if (usart_flag_get(s->USARTx, USART_ROERR_FLAG) == SET) {
|
if (usart_flag_get(s->USARTx, USART_ROERR_FLAG) == SET) {
|
||||||
usart_flag_clear(s->USARTx, USART_ROERR_FLAG);
|
usart_flag_clear(s->USARTx, USART_ROERR_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usart_flag_get(s->USARTx, USART_IDLEF_FLAG) == SET) {
|
if (usart_flag_get(s->USARTx, USART_IDLEF_FLAG) == SET) {
|
||||||
if (s->port.idleCallback) {
|
if (s->port.idleCallback) {
|
||||||
s->port.idleCallback();
|
s->port.idleCallback();
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART1_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART1_RX,
|
||||||
|
@ -120,7 +120,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART2_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART2_RX,
|
||||||
|
@ -151,7 +151,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART3_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART3_RX,
|
||||||
|
@ -182,7 +182,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART4_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART4_RX,
|
||||||
|
@ -213,7 +213,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART5_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART5_RX,
|
||||||
|
@ -246,7 +246,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
{
|
{
|
||||||
.device = UARTDEV_6,
|
.identifier = SERIAL_PORT_USART6,
|
||||||
.reg = USART6,
|
.reg = USART6,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART6_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_USART6_RX,
|
||||||
|
@ -279,7 +279,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART7
|
#ifdef USE_UART7
|
||||||
{
|
{
|
||||||
.device = UARTDEV_7,
|
.identifier = SERIAL_PORT_UART7,
|
||||||
.reg = UART7,
|
.reg = UART7,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART7_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART7_RX,
|
||||||
|
@ -313,7 +313,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART8
|
#ifdef USE_UART8
|
||||||
{
|
{
|
||||||
.device = UARTDEV_8,
|
.identifier = SERIAL_PORT_UART8,
|
||||||
.reg = UART8, //USE UART8 FOR PIN CONFIG
|
.reg = UART8, //USE UART8 FOR PIN CONFIG
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART8_RX,
|
.rxDMAMuxId = DMAMUX_DMAREQ_ID_UART8_RX,
|
||||||
|
@ -348,79 +348,4 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartDevice_t *uartdev = uartDevmap[device];
|
|
||||||
if (!uartdev) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uartPort_t *s = &(uartdev->port);
|
|
||||||
|
|
||||||
s->port.vTable = uartVTable;
|
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
|
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
|
||||||
|
|
||||||
s->USARTx = hardware->reg;
|
|
||||||
|
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uartdev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
|
||||||
|
|
||||||
uartdev->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if ((options & SERIAL_BIDIR) && txIO) {
|
|
||||||
//mode,speed,otype,pupd
|
|
||||||
ioConfig_t ioCfg = IO_CONFIG(
|
|
||||||
GPIO_MODE_MUX,
|
|
||||||
GPIO_DRIVE_STRENGTH_STRONGER,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_OUTPUT_PUSH_PULL : GPIO_OUTPUT_OPEN_DRAIN,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULL_DOWN : GPIO_PULL_UP
|
|
||||||
);
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
|
|
||||||
} else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (((options & SERIAL_INVERTED) == SERIAL_NOT_INVERTED) && !(options & SERIAL_BIDIR_PP_PD)) {
|
|
||||||
uartdev->txPinState = TX_PIN_ACTIVE;
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (!s->rxDMAResource)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
nvic_irq_enable(hardware->irqn,NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -40,8 +40,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -51,8 +49,6 @@
|
||||||
#define USE_UART7
|
#define USE_UART7
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 8)
|
|
||||||
|
|
||||||
#define TARGET_IO_PORTA 0xffff
|
#define TARGET_IO_PORTA 0xffff
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
|
|
@ -40,8 +40,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -51,8 +49,6 @@
|
||||||
#define USE_UART7
|
#define USE_UART7
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 8)
|
|
||||||
|
|
||||||
#define TARGET_IO_PORTA 0xffff
|
#define TARGET_IO_PORTA 0xffff
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
|
|
@ -92,8 +92,6 @@
|
||||||
#define USE_UART7
|
#define USE_UART7
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT 8
|
|
||||||
|
|
||||||
#define DEFAULT_RX_FEATURE FEATURE_RX_MSP
|
#define DEFAULT_RX_FEATURE FEATURE_RX_MSP
|
||||||
#define DEFAULT_FEATURES (FEATURE_GPS | FEATURE_TELEMETRY)
|
#define DEFAULT_FEATURES (FEATURE_GPS | FEATURE_TELEMETRY)
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ void adcInit(const adcConfig_t *config)
|
||||||
|
|
||||||
RCC_ClockCmd(adc->rccADC, ENABLE);
|
RCC_ClockCmd(adc->rccADC, ENABLE);
|
||||||
|
|
||||||
int configuredAdcChannels = BITCOUNT(adc->channelBits);
|
int configuredAdcChannels = popcount(adc->channelBits);
|
||||||
|
|
||||||
adcInitDevice(adc, configuredAdcChannels);
|
adcInitDevice(adc, configuredAdcChannels);
|
||||||
|
|
||||||
|
@ -472,11 +472,11 @@ void adcInit(const adcConfig_t *config)
|
||||||
|
|
||||||
// Start conversion in DMA mode
|
// Start conversion in DMA mode
|
||||||
|
|
||||||
if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t *)&adcConversionBuffer[dmaBufferIndex], BITCOUNT(adc->channelBits)) != HAL_OK) {
|
if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t *)&adcConversionBuffer[dmaBufferIndex], popcount(adc->channelBits)) != HAL_OK) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
|
|
||||||
dmaBufferIndex += BITCOUNT(adc->channelBits);
|
dmaBufferIndex += popcount(adc->channelBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,7 +424,7 @@ void adcInit(const adcConfig_t *config)
|
||||||
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);
|
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int configuredAdcChannels = BITCOUNT(adc->channelBits);
|
int configuredAdcChannels = popcount(adc->channelBits);
|
||||||
|
|
||||||
adcInitDevice(adc, configuredAdcChannels);
|
adcInitDevice(adc, configuredAdcChannels);
|
||||||
|
|
||||||
|
@ -529,11 +529,11 @@ void adcInit(const adcConfig_t *config)
|
||||||
|
|
||||||
// Start conversion in DMA mode
|
// Start conversion in DMA mode
|
||||||
|
|
||||||
if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t *)&adcConversionBuffer[dmaBufferIndex], BITCOUNT(adc->channelBits)) != HAL_OK) {
|
if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t *)&adcConversionBuffer[dmaBufferIndex], popcount(adc->channelBits)) != HAL_OK) {
|
||||||
errorHandler();
|
errorHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
dmaBufferIndex += BITCOUNT(adc->channelBits);
|
dmaBufferIndex += popcount(adc->channelBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ static const uint32_t quadSpi_addressSizeMap[] = {
|
||||||
|
|
||||||
static uint32_t quadSpi_addressSizeFromValue(uint8_t addressSize)
|
static uint32_t quadSpi_addressSizeFromValue(uint8_t addressSize)
|
||||||
{
|
{
|
||||||
|
// TODO addressSize + 7) / 8)
|
||||||
return quadSpi_addressSizeMap[((addressSize + 1) / 8) - 1]; // rounds to nearest QSPI_ADDRESS_* value that will hold the address.
|
return quadSpi_addressSizeMap[((addressSize + 1) / 8) - 1]; // rounds to nearest QSPI_ADDRESS_* value that will hold the address.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "drivers/dma_reqmap.h"
|
#include "drivers/dma_reqmap.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
#include "pg/timerio.h"
|
#include "pg/timerio.h"
|
||||||
|
|
||||||
|
@ -98,21 +99,29 @@ static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
|
||||||
REQMAP(ADC, 5),
|
REQMAP(ADC, 5),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART1
|
||||||
REQMAP_DIR(UART, 1, TX),
|
REQMAP_DIR(UART, 1, TX),
|
||||||
REQMAP_DIR(UART, 1, RX),
|
REQMAP_DIR(UART, 1, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
REQMAP_DIR(UART, 2, TX),
|
REQMAP_DIR(UART, 2, TX),
|
||||||
REQMAP_DIR(UART, 2, RX),
|
REQMAP_DIR(UART, 2, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
REQMAP_DIR(UART, 3, TX),
|
REQMAP_DIR(UART, 3, TX),
|
||||||
REQMAP_DIR(UART, 3, RX),
|
REQMAP_DIR(UART, 3, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
REQMAP_DIR(UART, 4, TX),
|
REQMAP_DIR(UART, 4, TX),
|
||||||
REQMAP_DIR(UART, 4, RX),
|
REQMAP_DIR(UART, 4, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
REQMAP_DIR(UART, 5, TX),
|
REQMAP_DIR(UART, 5, TX),
|
||||||
REQMAP_DIR(UART, 5, RX),
|
REQMAP_DIR(UART, 5, RX),
|
||||||
#ifdef USE_LPUART1
|
|
||||||
{ DMA_PERIPH_UART_TX, LPUARTDEV_1, DMA_REQUEST_LPUART1_TX },
|
|
||||||
{ DMA_PERIPH_UART_RX, LPUARTDEV_1, DMA_REQUEST_LPUART1_RX },
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_LPUART1
|
||||||
|
{ DMA_PERIPH_UART_TX, UARTDEV_LP1, DMA_REQUEST_LPUART1_TX },
|
||||||
|
{ DMA_PERIPH_UART_RX, UARTDEV_LP1, DMA_REQUEST_LPUART1_RX },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TIMER
|
#ifdef USE_TIMER
|
||||||
|
@ -256,33 +265,49 @@ static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART1
|
||||||
REQMAP_DIR(UART, 1, TX),
|
REQMAP_DIR(UART, 1, TX),
|
||||||
REQMAP_DIR(UART, 1, RX),
|
REQMAP_DIR(UART, 1, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
REQMAP_DIR(UART, 2, TX),
|
REQMAP_DIR(UART, 2, TX),
|
||||||
REQMAP_DIR(UART, 2, RX),
|
REQMAP_DIR(UART, 2, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
REQMAP_DIR(UART, 3, TX),
|
REQMAP_DIR(UART, 3, TX),
|
||||||
REQMAP_DIR(UART, 3, RX),
|
REQMAP_DIR(UART, 3, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
REQMAP_DIR(UART, 4, TX),
|
REQMAP_DIR(UART, 4, TX),
|
||||||
REQMAP_DIR(UART, 4, RX),
|
REQMAP_DIR(UART, 4, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
REQMAP_DIR(UART, 5, TX),
|
REQMAP_DIR(UART, 5, TX),
|
||||||
REQMAP_DIR(UART, 5, RX),
|
REQMAP_DIR(UART, 5, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
REQMAP_DIR(UART, 6, TX),
|
REQMAP_DIR(UART, 6, TX),
|
||||||
REQMAP_DIR(UART, 6, RX),
|
REQMAP_DIR(UART, 6, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART7
|
||||||
REQMAP_DIR(UART, 7, TX),
|
REQMAP_DIR(UART, 7, TX),
|
||||||
REQMAP_DIR(UART, 7, RX),
|
REQMAP_DIR(UART, 7, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART8
|
||||||
REQMAP_DIR(UART, 8, TX),
|
REQMAP_DIR(UART, 8, TX),
|
||||||
REQMAP_DIR(UART, 8, RX),
|
REQMAP_DIR(UART, 8, RX),
|
||||||
#if defined(STM32H7A3xxQ)
|
#endif
|
||||||
|
#ifdef USE_UART9
|
||||||
REQMAP_DIR(UART, 9, TX),
|
REQMAP_DIR(UART, 9, TX),
|
||||||
REQMAP_DIR(UART, 9, RX),
|
REQMAP_DIR(UART, 9, RX),
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART10
|
||||||
REQMAP_DIR(UART, 10, TX),
|
REQMAP_DIR(UART, 10, TX),
|
||||||
REQMAP_DIR(UART, 10, RX),
|
REQMAP_DIR(UART, 10, RX),
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
{ DMA_PERIPH_UART_TX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_TX },
|
{ DMA_PERIPH_UART_TX, UARTDEV_LP1, BDMA_REQUEST_LPUART1_TX },
|
||||||
{ DMA_PERIPH_UART_RX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_RX },
|
{ DMA_PERIPH_UART_RX, UARTDEV_LP1, BDMA_REQUEST_LPUART1_RX },
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TIMER
|
#ifdef USE_TIMER
|
||||||
|
@ -414,17 +439,27 @@ static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
|
||||||
{ DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
|
{ DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART1
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(2, 7, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(2, 7, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(2, 5, 4), DMA(2, 2, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(2, 5, 4), DMA(2, 2, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART2
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 6, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 6, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 5, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 5, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART3
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 3, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 3, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 1, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 1, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART4
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(1, 4, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(1, 4, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(1, 2, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(1, 2, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART5
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_5, { DMA(1, 7, 4) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_5, { DMA(1, 7, 4) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_5, { DMA(1, 0, 4) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_5, { DMA(1, 0, 4) } },
|
||||||
|
#endif
|
||||||
|
#ifdef USE_UART6
|
||||||
{ DMA_PERIPH_UART_TX, UARTDEV_6, { DMA(2, 6, 5), DMA(2, 7, 5) } },
|
{ DMA_PERIPH_UART_TX, UARTDEV_6, { DMA(2, 6, 5), DMA(2, 7, 5) } },
|
||||||
{ DMA_PERIPH_UART_RX, UARTDEV_6, { DMA(2, 1, 5), DMA(2, 2, 5) } },
|
{ DMA_PERIPH_UART_RX, UARTDEV_6, { DMA(2, 1, 5), DMA(2, 2, 5) } },
|
||||||
#endif
|
#endif
|
||||||
|
@ -485,8 +520,7 @@ const dmaChannelSpec_t *dmaGetChannelSpecByPeripheral(dmaPeripheral_e device, ui
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0 ; i < ARRAYLEN(dmaPeripheralMapping) ; i++) {
|
for (const dmaPeripheralMapping_t *periph = dmaPeripheralMapping; periph < ARRAYEND(dmaPeripheralMapping) ; periph++) {
|
||||||
const dmaPeripheralMapping_t *periph = &dmaPeripheralMapping[i];
|
|
||||||
#if defined(STM32H7) || defined(STM32G4)
|
#if defined(STM32H7) || defined(STM32G4)
|
||||||
if (periph->device == device && periph->index == index) {
|
if (periph->device == device && periph->index == index) {
|
||||||
dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[opt];
|
dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[opt];
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(STM32H7) || defined(STM32G4)
|
#if defined(STM32H7) || defined(STM32G4)
|
||||||
|
|
||||||
#define MAX_PERIPHERAL_DMA_OPTIONS 16
|
#define MAX_PERIPHERAL_DMA_OPTIONS 16
|
||||||
#define MAX_TIMER_DMA_OPTIONS 16
|
#define MAX_TIMER_DMA_OPTIONS 16
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -67,26 +67,10 @@ static void usartConfigurePinInversion(uartPort_t *uartPort)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uartDevice_t *uartFindDevice(const uartPort_t *uartPort)
|
#if UART_TRAIT_PINSWAP
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < UARTDEV_COUNT_MAX; i++) {
|
|
||||||
uartDevice_t *candidate = uartDevmap[i];
|
|
||||||
|
|
||||||
if (&candidate->port == uartPort) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !(defined(STM32F4))
|
|
||||||
static void uartConfigurePinSwap(uartPort_t *uartPort)
|
static void uartConfigurePinSwap(uartPort_t *uartPort)
|
||||||
{
|
{
|
||||||
uartDevice_t *uartDevice = uartFindDevice(uartPort);
|
uartDevice_t *uartDevice = container_of(uartPort, uartDevice_t, port);
|
||||||
if (!uartDevice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uartDevice->pinSwap) {
|
if (uartDevice->pinSwap) {
|
||||||
uartDevice->port.Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_SWAP_INIT;
|
uartDevice->port.Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_SWAP_INIT;
|
||||||
uartDevice->port.Handle.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;
|
uartDevice->port.Handle.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;
|
||||||
|
@ -130,12 +114,9 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
usartTargetConfigure(uartPort);
|
usartTargetConfigure(uartPort);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (uartPort->port.options & SERIAL_BIDIR)
|
if (uartPort->port.options & SERIAL_BIDIR) {
|
||||||
{
|
|
||||||
HAL_HalfDuplex_Init(&uartPort->Handle);
|
HAL_HalfDuplex_Init(&uartPort->Handle);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
HAL_UART_Init(&uartPort->Handle);
|
HAL_UART_Init(&uartPort->Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,22 +48,6 @@
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
static void usartConfigurePinInversion(uartPort_t *uartPort)
|
|
||||||
{
|
|
||||||
#if !defined(USE_INVERTER)
|
|
||||||
UNUSED(uartPort);
|
|
||||||
#else
|
|
||||||
bool inverted = uartPort->port.options & SERIAL_INVERTED;
|
|
||||||
|
|
||||||
#ifdef USE_INVERTER
|
|
||||||
if (inverted) {
|
|
||||||
// Enable hardware inverter if available.
|
|
||||||
enableInverter(uartPort->USARTx, true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartReconfigure(uartPort_t *uartPort)
|
void uartReconfigure(uartPort_t *uartPort)
|
||||||
{
|
{
|
||||||
USART_InitTypeDef USART_InitStructure;
|
USART_InitTypeDef USART_InitStructure;
|
||||||
|
@ -91,7 +75,8 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
|
|
||||||
USART_Init(uartPort->USARTx, &USART_InitStructure);
|
USART_Init(uartPort->USARTx, &USART_InitStructure);
|
||||||
|
|
||||||
usartConfigurePinInversion(uartPort);
|
// config external pin inverter (no internal pin inversion available)
|
||||||
|
uartConfigureExternalPinInversion(uartPort);
|
||||||
|
|
||||||
if (uartPort->port.options & SERIAL_BIDIR)
|
if (uartPort->port.options & SERIAL_BIDIR)
|
||||||
USART_HalfDuplexCmd(uartPort->USARTx, ENABLE);
|
USART_HalfDuplexCmd(uartPort->USARTx, ENABLE);
|
||||||
|
@ -103,6 +88,7 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
// Receive DMA or IRQ
|
// Receive DMA or IRQ
|
||||||
DMA_InitTypeDef DMA_InitStructure;
|
DMA_InitTypeDef DMA_InitStructure;
|
||||||
if (uartPort->port.mode & MODE_RX) {
|
if (uartPort->port.mode & MODE_RX) {
|
||||||
|
#ifdef USE_DMA
|
||||||
if (uartPort->rxDMAResource) {
|
if (uartPort->rxDMAResource) {
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
DMA_StructInit(&DMA_InitStructure);
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||||
|
@ -133,7 +119,9 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
xDMA_Cmd(uartPort->rxDMAResource, ENABLE);
|
xDMA_Cmd(uartPort->rxDMAResource, ENABLE);
|
||||||
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Rx, ENABLE);
|
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Rx, ENABLE);
|
||||||
uartPort->rxDMAPos = xDMA_GetCurrDataCounter(uartPort->rxDMAResource);
|
uartPort->rxDMAPos = xDMA_GetCurrDataCounter(uartPort->rxDMAResource);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
USART_ClearITPendingBit(uartPort->USARTx, USART_IT_RXNE);
|
USART_ClearITPendingBit(uartPort->USARTx, USART_IT_RXNE);
|
||||||
USART_ITConfig(uartPort->USARTx, USART_IT_RXNE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_RXNE, ENABLE);
|
||||||
USART_ITConfig(uartPort->USARTx, USART_IT_IDLE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_IDLE, ENABLE);
|
||||||
|
@ -142,6 +130,7 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
|
|
||||||
// Transmit DMA or IRQ
|
// Transmit DMA or IRQ
|
||||||
if (uartPort->port.mode & MODE_TX) {
|
if (uartPort->port.mode & MODE_TX) {
|
||||||
|
#ifdef USE_DMA
|
||||||
if (uartPort->txDMAResource) {
|
if (uartPort->txDMAResource) {
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
DMA_StructInit(&DMA_InitStructure);
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||||
|
@ -177,14 +166,16 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
|
|
||||||
xDMA_SetCurrDataCounter(uartPort->txDMAResource, 0);
|
xDMA_SetCurrDataCounter(uartPort->txDMAResource, 0);
|
||||||
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Tx, ENABLE);
|
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Tx, ENABLE);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
USART_ITConfig(uartPort->USARTx, USART_IT_TXE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_TXE, ENABLE);
|
||||||
}
|
}
|
||||||
// Enable the interrupt so completion of the transmission will be signalled
|
// Enable the interrupt so completion of the transmission will be signalled
|
||||||
USART_ITConfig(uartPort->USARTx, USART_IT_TC, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_TC, ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
USART_Cmd(uartPort->USARTx, ENABLE);
|
USART_Cmd(uartPort->USARTx, ENABLE); // TODO : enabling twice?
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
|
@ -209,7 +200,7 @@ void uartTryStartTxDMA(uartPort_t *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->port.txBufferHead == s->port.txBufferTail) {
|
if (s->port.txBufferHead == s->port.txBufferTail) {
|
||||||
// No more data to transmit.
|
// No more data to transmit
|
||||||
s->txDMAEmpty = true;
|
s->txDMAEmpty = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -222,15 +213,16 @@ void uartTryStartTxDMA(uartPort_t *s)
|
||||||
DMAx_SetMemoryAddress(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail]);
|
DMAx_SetMemoryAddress(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned chunk;
|
||||||
if (s->port.txBufferHead > s->port.txBufferTail) {
|
if (s->port.txBufferHead > s->port.txBufferTail) {
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferHead - s->port.txBufferTail);
|
chunk = s->port.txBufferHead - s->port.txBufferTail;
|
||||||
s->port.txBufferTail = s->port.txBufferHead;
|
s->port.txBufferTail = s->port.txBufferHead;
|
||||||
} else {
|
} else {
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferSize - s->port.txBufferTail);
|
chunk = s->port.txBufferSize - s->port.txBufferTail;
|
||||||
s->port.txBufferTail = 0;
|
s->port.txBufferTail = 0;
|
||||||
}
|
}
|
||||||
s->txDMAEmpty = false;
|
s->txDMAEmpty = false;
|
||||||
|
xDMA_SetCurrDataCounter(s->txDMAResource, chunk);
|
||||||
reenable:
|
reenable:
|
||||||
xDMA_Cmd(s->txDMAResource, ENABLE);
|
xDMA_Cmd(s->txDMAResource, ENABLE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "build/debug.h"
|
|
||||||
|
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
.rxDMAChannel = DMA_Channel_4,
|
.rxDMAChannel = DMA_Channel_4,
|
||||||
.txDMAChannel = DMA_Channel_4,
|
.txDMAChannel = DMA_Channel_4,
|
||||||
|
@ -79,7 +78,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
.rxDMAChannel = DMA_Channel_4,
|
.rxDMAChannel = DMA_Channel_4,
|
||||||
.txDMAChannel = DMA_Channel_4,
|
.txDMAChannel = DMA_Channel_4,
|
||||||
|
@ -105,7 +104,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
.rxDMAChannel = DMA_Channel_4,
|
.rxDMAChannel = DMA_Channel_4,
|
||||||
.txDMAChannel = DMA_Channel_4,
|
.txDMAChannel = DMA_Channel_4,
|
||||||
|
@ -131,7 +130,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
.rxDMAChannel = DMA_Channel_4,
|
.rxDMAChannel = DMA_Channel_4,
|
||||||
.txDMAChannel = DMA_Channel_4,
|
.txDMAChannel = DMA_Channel_4,
|
||||||
|
@ -157,7 +156,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
.rxDMAChannel = DMA_Channel_4,
|
.rxDMAChannel = DMA_Channel_4,
|
||||||
.txDMAChannel = DMA_Channel_4,
|
.txDMAChannel = DMA_Channel_4,
|
||||||
|
@ -183,7 +182,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
{
|
{
|
||||||
.device = UARTDEV_6,
|
.identifier = SERIAL_PORT_USART6,
|
||||||
.reg = USART6,
|
.reg = USART6,
|
||||||
.rxDMAChannel = DMA_Channel_5,
|
.rxDMAChannel = DMA_Channel_5,
|
||||||
.txDMAChannel = DMA_Channel_5,
|
.txDMAChannel = DMA_Channel_5,
|
||||||
|
@ -297,83 +296,6 @@ void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Should serialUART be consolidated?
|
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartDevice_t *uart = uartDevmap[device];
|
|
||||||
if (!uart) return NULL;
|
|
||||||
|
|
||||||
const uartHardware_t *hardware = uart->hardware;
|
|
||||||
|
|
||||||
if (!hardware) return NULL; // XXX Can't happen !?
|
|
||||||
|
|
||||||
uartPort_t *s = &(uart->port);
|
|
||||||
s->port.vTable = uartVTable;
|
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
|
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->USARTx = hardware->reg;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uart);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uart->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uart->rx.pin);
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
uart->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if (options & SERIAL_BIDIR) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, (options & SERIAL_BIDIR_PP_PD) ? IOCFG_AF_PP_PD
|
|
||||||
: (options & SERIAL_BIDIR_PP) ? IOCFG_AF_PP
|
|
||||||
: IOCFG_AF_OD, hardware->af);
|
|
||||||
} else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (options & SERIAL_CHECK_TX) {
|
|
||||||
uart->txPinState = TX_PIN_ACTIVE;
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP_UP, hardware->af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP_UP, hardware->af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (!(s->rxDMAResource)) {
|
|
||||||
NVIC_InitTypeDef NVIC_InitStructure;
|
|
||||||
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = hardware->irqn;
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(hardware->rxPriority);
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(hardware->rxPriority);
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
||||||
NVIC_Init(&NVIC_InitStructure);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartIrqHandler(uartPort_t *s)
|
void uartIrqHandler(uartPort_t *s)
|
||||||
{
|
{
|
||||||
if (!s->rxDMAResource && (USART_GetITStatus(s->USARTx, USART_IT_RXNE) == SET)) {
|
if (!s->rxDMAResource && (USART_GetITStatus(s->USARTx, USART_IT_RXNE) == SET)) {
|
||||||
|
@ -416,4 +338,4 @@ void uartIrqHandler(uartPort_t *s)
|
||||||
(void) s->USARTx->DR;
|
(void) s->USARTx->DR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // USE_UART
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -69,7 +69,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART1),
|
.rcc = RCC_APB2(USART1),
|
||||||
.rxIrq = USART1_IRQn,
|
.irqn = USART1_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART1,
|
.rxPriority = NVIC_PRIO_SERIALUART1,
|
||||||
.txBuffer = uart1TxBuffer,
|
.txBuffer = uart1TxBuffer,
|
||||||
|
@ -81,7 +81,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -100,7 +100,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD5), GPIO_AF7_USART2 }
|
{ DEFIO_TAG_E(PD5), GPIO_AF7_USART2 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(USART2),
|
.rcc = RCC_APB1(USART2),
|
||||||
.rxIrq = USART2_IRQn,
|
.irqn = USART2_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART2,
|
.rxPriority = NVIC_PRIO_SERIALUART2,
|
||||||
.txBuffer = uart2TxBuffer,
|
.txBuffer = uart2TxBuffer,
|
||||||
|
@ -112,7 +112,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -133,7 +133,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD8), GPIO_AF7_USART3 }
|
{ DEFIO_TAG_E(PD8), GPIO_AF7_USART3 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(USART3),
|
.rcc = RCC_APB1(USART3),
|
||||||
.rxIrq = USART3_IRQn,
|
.irqn = USART3_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART3,
|
.rxPriority = NVIC_PRIO_SERIALUART3,
|
||||||
.txBuffer = uart3TxBuffer,
|
.txBuffer = uart3TxBuffer,
|
||||||
|
@ -145,7 +145,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -172,7 +172,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(UART4),
|
.rcc = RCC_APB1(UART4),
|
||||||
.rxIrq = UART4_IRQn,
|
.irqn = UART4_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART4,
|
.rxPriority = NVIC_PRIO_SERIALUART4,
|
||||||
.txBuffer = uart4TxBuffer,
|
.txBuffer = uart4TxBuffer,
|
||||||
|
@ -184,7 +184,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
.rxDMAChannel = DMA_CHANNEL_4,
|
.rxDMAChannel = DMA_CHANNEL_4,
|
||||||
.txDMAChannel = DMA_CHANNEL_4,
|
.txDMAChannel = DMA_CHANNEL_4,
|
||||||
|
@ -211,7 +211,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(UART5),
|
.rcc = RCC_APB1(UART5),
|
||||||
.rxIrq = UART5_IRQn,
|
.irqn = UART5_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART5,
|
.rxPriority = NVIC_PRIO_SERIALUART5,
|
||||||
.txBuffer = uart5TxBuffer,
|
.txBuffer = uart5TxBuffer,
|
||||||
|
@ -223,7 +223,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
{
|
{
|
||||||
.device = UARTDEV_6,
|
.identifier = SERIAL_PORT_USART6,
|
||||||
.reg = USART6,
|
.reg = USART6,
|
||||||
.rxDMAChannel = DMA_CHANNEL_5,
|
.rxDMAChannel = DMA_CHANNEL_5,
|
||||||
.txDMAChannel = DMA_CHANNEL_5,
|
.txDMAChannel = DMA_CHANNEL_5,
|
||||||
|
@ -242,7 +242,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PG14), GPIO_AF8_USART6 }
|
{ DEFIO_TAG_E(PG14), GPIO_AF8_USART6 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART6),
|
.rcc = RCC_APB2(USART6),
|
||||||
.rxIrq = USART6_IRQn,
|
.irqn = USART6_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART6,
|
.rxPriority = NVIC_PRIO_SERIALUART6,
|
||||||
.txBuffer = uart6TxBuffer,
|
.txBuffer = uart6TxBuffer,
|
||||||
|
@ -254,7 +254,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART7
|
#ifdef USE_UART7
|
||||||
{
|
{
|
||||||
.device = UARTDEV_7,
|
.identifier = SERIAL_PORT_UART7,
|
||||||
.reg = UART7,
|
.reg = UART7,
|
||||||
.rxDMAChannel = DMA_CHANNEL_5,
|
.rxDMAChannel = DMA_CHANNEL_5,
|
||||||
.txDMAChannel = DMA_CHANNEL_5,
|
.txDMAChannel = DMA_CHANNEL_5,
|
||||||
|
@ -281,7 +281,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(UART7),
|
.rcc = RCC_APB1(UART7),
|
||||||
.rxIrq = UART7_IRQn,
|
.irqn = UART7_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART7_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART7_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART7,
|
.rxPriority = NVIC_PRIO_SERIALUART7,
|
||||||
.txBuffer = uart7TxBuffer,
|
.txBuffer = uart7TxBuffer,
|
||||||
|
@ -293,7 +293,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART8
|
#ifdef USE_UART8
|
||||||
{
|
{
|
||||||
.device = UARTDEV_8,
|
.identifier = SERIAL_PORT_UART8,
|
||||||
.reg = UART8,
|
.reg = UART8,
|
||||||
.rxDMAChannel = DMA_CHANNEL_5,
|
.rxDMAChannel = DMA_CHANNEL_5,
|
||||||
.txDMAChannel = DMA_CHANNEL_5,
|
.txDMAChannel = DMA_CHANNEL_5,
|
||||||
|
@ -310,7 +310,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PE1), GPIO_AF8_UART8 }
|
{ DEFIO_TAG_E(PE1), GPIO_AF8_UART8 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1(UART8),
|
.rcc = RCC_APB1(UART8),
|
||||||
.rxIrq = UART8_IRQn,
|
.irqn = UART8_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART8_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART8_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART8,
|
.rxPriority = NVIC_PRIO_SERIALUART8,
|
||||||
.txBuffer = uart8TxBuffer,
|
.txBuffer = uart8TxBuffer,
|
||||||
|
@ -321,83 +321,4 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX Should serialUART be consolidated?
|
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartDevice_t *uartdev = uartDevmap[device];
|
|
||||||
if (!uartdev) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uartPort_t *s = &(uartdev->port);
|
|
||||||
|
|
||||||
s->port.vTable = uartVTable;
|
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
|
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
|
||||||
|
|
||||||
s->USARTx = hardware->reg;
|
|
||||||
|
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uartdev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->Handle.Instance = hardware->reg;
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
|
||||||
|
|
||||||
uartdev->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if ((options & SERIAL_BIDIR) && txIO) {
|
|
||||||
ioConfig_t ioCfg = IO_CONFIG(
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
|
|
||||||
GPIO_SPEED_FREQ_HIGH,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULLDOWN : GPIO_PULLUP
|
|
||||||
);
|
|
||||||
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (options & SERIAL_CHECK_TX) {
|
|
||||||
uartdev->txPinState = TX_PIN_MONITOR;
|
|
||||||
// Switch TX to UART output whilst UART sends idle preamble
|
|
||||||
checkUsartTxOutput(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (!s->rxDMAResource) {
|
|
||||||
HAL_NVIC_SetPriority(hardware->rxIrq, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
|
||||||
HAL_NVIC_EnableIRQ(hardware->rxIrq);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART1_RX,
|
.rxDMAChannel = DMA_REQUEST_USART1_RX,
|
||||||
|
@ -96,7 +96,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC4), GPIO_AF7_USART1 },
|
{ DEFIO_TAG_E(PC4), GPIO_AF7_USART1 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART1),
|
.rcc = RCC_APB2(USART1),
|
||||||
.rxIrq = USART1_IRQn,
|
.irqn = USART1_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART1,
|
.rxPriority = NVIC_PRIO_SERIALUART1,
|
||||||
.txBuffer = uart1TxBuffer,
|
.txBuffer = uart1TxBuffer,
|
||||||
|
@ -108,7 +108,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART2_RX,
|
.rxDMAChannel = DMA_REQUEST_USART2_RX,
|
||||||
|
@ -127,7 +127,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PB3), GPIO_AF7_USART2 },
|
{ DEFIO_TAG_E(PB3), GPIO_AF7_USART2 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB11(USART2),
|
.rcc = RCC_APB11(USART2),
|
||||||
.rxIrq = USART2_IRQn,
|
.irqn = USART2_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART2,
|
.rxPriority = NVIC_PRIO_SERIALUART2,
|
||||||
.txBuffer = uart2TxBuffer,
|
.txBuffer = uart2TxBuffer,
|
||||||
|
@ -139,7 +139,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART3_RX,
|
.rxDMAChannel = DMA_REQUEST_USART3_RX,
|
||||||
|
@ -158,7 +158,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC10), GPIO_AF7_USART3 },
|
{ DEFIO_TAG_E(PC10), GPIO_AF7_USART3 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB11(USART3),
|
.rcc = RCC_APB11(USART3),
|
||||||
.rxIrq = USART3_IRQn,
|
.irqn = USART3_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART3,
|
.rxPriority = NVIC_PRIO_SERIALUART3,
|
||||||
.txBuffer = uart3TxBuffer,
|
.txBuffer = uart3TxBuffer,
|
||||||
|
@ -170,7 +170,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART4_RX,
|
.rxDMAChannel = DMA_REQUEST_UART4_RX,
|
||||||
|
@ -185,7 +185,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC10), GPIO_AF5_UART4 },
|
{ DEFIO_TAG_E(PC10), GPIO_AF5_UART4 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB11(UART4),
|
.rcc = RCC_APB11(UART4),
|
||||||
.rxIrq = UART4_IRQn,
|
.irqn = UART4_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART4,
|
.rxPriority = NVIC_PRIO_SERIALUART4,
|
||||||
.txBuffer = uart4TxBuffer,
|
.txBuffer = uart4TxBuffer,
|
||||||
|
@ -197,7 +197,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART5_RX,
|
.rxDMAChannel = DMA_REQUEST_UART5_RX,
|
||||||
|
@ -212,7 +212,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC12), GPIO_AF5_UART5 },
|
{ DEFIO_TAG_E(PC12), GPIO_AF5_UART5 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB11(UART5),
|
.rcc = RCC_APB11(UART5),
|
||||||
.rxIrq = UART5_IRQn,
|
.irqn = UART5_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART5,
|
.rxPriority = NVIC_PRIO_SERIALUART5,
|
||||||
.txBuffer = uart5TxBuffer,
|
.txBuffer = uart5TxBuffer,
|
||||||
|
@ -224,7 +224,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
{
|
{
|
||||||
.device = LPUARTDEV_1,
|
.identifier = SERIAL_PORT_LPUART1,
|
||||||
.reg = LPUART1,
|
.reg = LPUART1,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_LPUART1_RX,
|
.rxDMAChannel = DMA_REQUEST_LPUART1_RX,
|
||||||
|
@ -243,95 +243,15 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC1), GPIO_AF8_LPUART1 },
|
{ DEFIO_TAG_E(PC1), GPIO_AF8_LPUART1 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB12(LPUART1),
|
.rcc = RCC_APB12(LPUART1),
|
||||||
.rxIrq = LPUART1_IRQn,
|
.irqn = LPUART1_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART6,
|
.rxPriority = NVIC_PRIO_SERIALUART6,
|
||||||
.txBuffer = lpuart1TxBuffer,
|
.txBuffer = uartLp1TxBuffer,
|
||||||
.rxBuffer = lpuart1RxBuffer,
|
.rxBuffer = uartLp1RxBuffer,
|
||||||
.txBufferSize = sizeof(lpuart1TxBuffer),
|
.txBufferSize = sizeof(uartLp1TxBuffer),
|
||||||
.rxBufferSize = sizeof(lpuart1RxBuffer),
|
.rxBufferSize = sizeof(uartLp1RxBuffer),
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// XXX Should serialUART be consolidated?
|
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartDevice_t *uartdev = uartDevmap[device];
|
|
||||||
if (!uartdev) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uartPort_t *s = &(uartdev->port);
|
|
||||||
|
|
||||||
s->port.vTable = uartVTable;
|
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
|
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
|
||||||
|
|
||||||
s->USARTx = hardware->reg;
|
|
||||||
|
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uartdev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->Handle.Instance = hardware->reg;
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
|
||||||
|
|
||||||
uartdev->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if ((options & SERIAL_BIDIR) && txIO) {
|
|
||||||
ioConfig_t ioCfg = IO_CONFIG(
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
|
|
||||||
GPIO_SPEED_FREQ_HIGH,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULLDOWN : GPIO_PULLUP
|
|
||||||
);
|
|
||||||
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
|
|
||||||
} else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (options & SERIAL_CHECK_TX) {
|
|
||||||
uartdev->txPinState = TX_PIN_ACTIVE;
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (!s->rxDMAResource)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
HAL_NVIC_SetPriority(hardware->rxIrq, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
|
||||||
HAL_NVIC_EnableIRQ(hardware->rxIrq);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
{
|
{
|
||||||
.device = UARTDEV_1,
|
.identifier = SERIAL_PORT_USART1,
|
||||||
.reg = USART1,
|
.reg = USART1,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART1_RX,
|
.rxDMAChannel = DMA_REQUEST_USART1_RX,
|
||||||
|
@ -122,7 +122,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PB14), GPIO_AF4_USART1 },
|
{ DEFIO_TAG_E(PB14), GPIO_AF4_USART1 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART1),
|
.rcc = RCC_APB2(USART1),
|
||||||
.rxIrq = USART1_IRQn,
|
.irqn = USART1_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART1,
|
.rxPriority = NVIC_PRIO_SERIALUART1,
|
||||||
.txBuffer = uart1TxBuffer,
|
.txBuffer = uart1TxBuffer,
|
||||||
|
@ -134,7 +134,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
{
|
{
|
||||||
.device = UARTDEV_2,
|
.identifier = SERIAL_PORT_USART2,
|
||||||
.reg = USART2,
|
.reg = USART2,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART2_RX,
|
.rxDMAChannel = DMA_REQUEST_USART2_RX,
|
||||||
|
@ -151,7 +151,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD5), GPIO_AF7_USART2 }
|
{ DEFIO_TAG_E(PD5), GPIO_AF7_USART2 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(USART2),
|
.rcc = RCC_APB1L(USART2),
|
||||||
.rxIrq = USART2_IRQn,
|
.irqn = USART2_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART2,
|
.rxPriority = NVIC_PRIO_SERIALUART2,
|
||||||
.txBuffer = uart2TxBuffer,
|
.txBuffer = uart2TxBuffer,
|
||||||
|
@ -163,7 +163,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
{
|
{
|
||||||
.device = UARTDEV_3,
|
.identifier = SERIAL_PORT_USART3,
|
||||||
.reg = USART3,
|
.reg = USART3,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART3_RX,
|
.rxDMAChannel = DMA_REQUEST_USART3_RX,
|
||||||
|
@ -182,7 +182,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD8), GPIO_AF7_USART3 }
|
{ DEFIO_TAG_E(PD8), GPIO_AF7_USART3 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(USART3),
|
.rcc = RCC_APB1L(USART3),
|
||||||
.rxIrq = USART3_IRQn,
|
.irqn = USART3_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART3,
|
.rxPriority = NVIC_PRIO_SERIALUART3,
|
||||||
.txBuffer = uart3TxBuffer,
|
.txBuffer = uart3TxBuffer,
|
||||||
|
@ -194,7 +194,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
{
|
{
|
||||||
.device = UARTDEV_4,
|
.identifier = SERIAL_PORT_UART4,
|
||||||
.reg = UART4,
|
.reg = UART4,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART4_RX,
|
.rxDMAChannel = DMA_REQUEST_UART4_RX,
|
||||||
|
@ -217,7 +217,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD1), GPIO_AF8_UART4 }
|
{ DEFIO_TAG_E(PD1), GPIO_AF8_UART4 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(UART4),
|
.rcc = RCC_APB1L(UART4),
|
||||||
.rxIrq = UART4_IRQn,
|
.irqn = UART4_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART4,
|
.rxPriority = NVIC_PRIO_SERIALUART4,
|
||||||
.txBuffer = uart4TxBuffer,
|
.txBuffer = uart4TxBuffer,
|
||||||
|
@ -229,7 +229,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
{
|
{
|
||||||
.device = UARTDEV_5,
|
.identifier = SERIAL_PORT_UART5,
|
||||||
.reg = UART5,
|
.reg = UART5,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART5_RX,
|
.rxDMAChannel = DMA_REQUEST_UART5_RX,
|
||||||
|
@ -248,7 +248,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PC12), GPIO_AF8_UART5 },
|
{ DEFIO_TAG_E(PC12), GPIO_AF8_UART5 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(UART5),
|
.rcc = RCC_APB1L(UART5),
|
||||||
.rxIrq = UART5_IRQn,
|
.irqn = UART5_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART5,
|
.rxPriority = NVIC_PRIO_SERIALUART5,
|
||||||
.txBuffer = uart5TxBuffer,
|
.txBuffer = uart5TxBuffer,
|
||||||
|
@ -260,7 +260,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
{
|
{
|
||||||
.device = UARTDEV_6,
|
.identifier = SERIAL_PORT_USART6,
|
||||||
.reg = USART6,
|
.reg = USART6,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART6_RX,
|
.rxDMAChannel = DMA_REQUEST_USART6_RX,
|
||||||
|
@ -277,7 +277,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PG14), GPIO_AF7_USART6 }
|
{ DEFIO_TAG_E(PG14), GPIO_AF7_USART6 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART6),
|
.rcc = RCC_APB2(USART6),
|
||||||
.rxIrq = USART6_IRQn,
|
.irqn = USART6_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART6,
|
.rxPriority = NVIC_PRIO_SERIALUART6,
|
||||||
.txBuffer = uart6TxBuffer,
|
.txBuffer = uart6TxBuffer,
|
||||||
|
@ -289,7 +289,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART7
|
#ifdef USE_UART7
|
||||||
{
|
{
|
||||||
.device = UARTDEV_7,
|
.identifier = SERIAL_PORT_USART7,
|
||||||
.reg = UART7,
|
.reg = UART7,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART7_RX,
|
.rxDMAChannel = DMA_REQUEST_UART7_RX,
|
||||||
|
@ -310,7 +310,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PF7), GPIO_AF7_UART7 },
|
{ DEFIO_TAG_E(PF7), GPIO_AF7_UART7 },
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(UART7),
|
.rcc = RCC_APB1L(UART7),
|
||||||
.rxIrq = UART7_IRQn,
|
.irqn = UART7_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART7_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART7_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART7,
|
.rxPriority = NVIC_PRIO_SERIALUART7,
|
||||||
.txBuffer = uart7TxBuffer,
|
.txBuffer = uart7TxBuffer,
|
||||||
|
@ -322,7 +322,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART8
|
#ifdef USE_UART8
|
||||||
{
|
{
|
||||||
.device = UARTDEV_8,
|
.identifier = SERIAL_PORT_USART8,
|
||||||
.reg = UART8,
|
.reg = UART8,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART8_RX,
|
.rxDMAChannel = DMA_REQUEST_UART8_RX,
|
||||||
|
@ -337,7 +337,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PE1), GPIO_AF8_UART8 }
|
{ DEFIO_TAG_E(PE1), GPIO_AF8_UART8 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB1L(UART8),
|
.rcc = RCC_APB1L(UART8),
|
||||||
.rxIrq = UART8_IRQn,
|
.irqn = UART8_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART8_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART8_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART8,
|
.rxPriority = NVIC_PRIO_SERIALUART8,
|
||||||
.txBuffer = uart8TxBuffer,
|
.txBuffer = uart8TxBuffer,
|
||||||
|
@ -349,7 +349,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART9
|
#ifdef USE_UART9
|
||||||
{
|
{
|
||||||
.device = UARTDEV_9,
|
.identifier = SERIAL_PORT_UART9,
|
||||||
.reg = UART9,
|
.reg = UART9,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_UART9_RX,
|
.rxDMAChannel = DMA_REQUEST_UART9_RX,
|
||||||
|
@ -364,7 +364,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PD15), GPIO_AF11_UART9 }
|
{ DEFIO_TAG_E(PD15), GPIO_AF11_UART9 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(UART9),
|
.rcc = RCC_APB2(UART9),
|
||||||
.rxIrq = UART9_IRQn,
|
.irqn = UART9_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART9_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART9_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART9,
|
.rxPriority = NVIC_PRIO_SERIALUART9,
|
||||||
.txBuffer = uart9TxBuffer,
|
.txBuffer = uart9TxBuffer,
|
||||||
|
@ -376,7 +376,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_UART10
|
#ifdef USE_UART10
|
||||||
{
|
{
|
||||||
.device = UARTDEV_10,
|
.identifier = SERIAL_PORT_USART10,
|
||||||
.reg = USART10,
|
.reg = USART10,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = DMA_REQUEST_USART10_RX,
|
.rxDMAChannel = DMA_REQUEST_USART10_RX,
|
||||||
|
@ -391,7 +391,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PE3), GPIO_AF11_USART10 }
|
{ DEFIO_TAG_E(PE3), GPIO_AF11_USART10 }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB2(USART10),
|
.rcc = RCC_APB2(USART10),
|
||||||
.rxIrq = USART10_IRQn,
|
.irqn = USART10_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALUART10_TXDMA,
|
.txPriority = NVIC_PRIO_SERIALUART10_TXDMA,
|
||||||
.rxPriority = NVIC_PRIO_SERIALUART10,
|
.rxPriority = NVIC_PRIO_SERIALUART10,
|
||||||
.txBuffer = uart10TxBuffer,
|
.txBuffer = uart10TxBuffer,
|
||||||
|
@ -403,7 +403,7 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
|
|
||||||
#ifdef USE_LPUART1
|
#ifdef USE_LPUART1
|
||||||
{
|
{
|
||||||
.device = LPUARTDEV_1,
|
.identifier = SERIAL_PORT_LPUART1,
|
||||||
.reg = LPUART1,
|
.reg = LPUART1,
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
.rxDMAChannel = BDMA_REQUEST_LPUART1_RX,
|
.rxDMAChannel = BDMA_REQUEST_LPUART1_RX,
|
||||||
|
@ -420,95 +420,16 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
|
||||||
{ DEFIO_TAG_E(PB6), GPIO_AF8_LPUART }
|
{ DEFIO_TAG_E(PB6), GPIO_AF8_LPUART }
|
||||||
},
|
},
|
||||||
.rcc = RCC_APB4(LPUART1),
|
.rcc = RCC_APB4(LPUART1),
|
||||||
.rxIrq = LPUART1_IRQn,
|
.irqn = LPUART1_IRQn,
|
||||||
.txPriority = NVIC_PRIO_SERIALLPUART1_TXDMA, // Not used until DMA is supported
|
.txPriority = NVIC_PRIO_SERIALLPUART1_TXDMA, // Not used until DMA is supported
|
||||||
.rxPriority = NVIC_PRIO_SERIALLPUART1, // Not used until DMA is supported
|
.rxPriority = NVIC_PRIO_SERIALLPUART1, // Not used until DMA is supported
|
||||||
.txBuffer = lpuart1TxBuffer,
|
.txBuffer = uartLp1TxBuffer,
|
||||||
.rxBuffer = lpuart1RxBuffer,
|
.rxBuffer = uartLp1RxBuffer,
|
||||||
.txBufferSize = sizeof(lpuart1TxBuffer),
|
.txBufferSize = sizeof(uartLp1TxBuffer),
|
||||||
.rxBufferSize = sizeof(lpuart1RxBuffer),
|
.rxBufferSize = sizeof(uartLp1RxBuffer),
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX Should serialUART be consolidated?
|
|
||||||
|
|
||||||
uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartDevice_t *uartdev = uartDevmap[device];
|
|
||||||
if (!uartdev) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uartPort_t *s = &(uartdev->port);
|
|
||||||
|
|
||||||
s->port.vTable = uartVTable;
|
|
||||||
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
|
|
||||||
const uartHardware_t *hardware = uartdev->hardware;
|
|
||||||
|
|
||||||
s->USARTx = hardware->reg;
|
|
||||||
|
|
||||||
s->port.rxBuffer = hardware->rxBuffer;
|
|
||||||
s->port.txBuffer = hardware->txBuffer;
|
|
||||||
s->port.rxBufferSize = hardware->rxBufferSize;
|
|
||||||
s->port.txBufferSize = hardware->txBufferSize;
|
|
||||||
|
|
||||||
s->checkUsartTxOutput = checkUsartTxOutput;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
uartConfigureDma(uartdev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->Handle.Instance = hardware->reg;
|
|
||||||
|
|
||||||
if (hardware->rcc) {
|
|
||||||
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_t txIO = IOGetByTag(uartdev->tx.pin);
|
|
||||||
IO_t rxIO = IOGetByTag(uartdev->rx.pin);
|
|
||||||
|
|
||||||
uartdev->txPinState = TX_PIN_IGNORE;
|
|
||||||
|
|
||||||
if ((options & SERIAL_BIDIR) && txIO) {
|
|
||||||
ioConfig_t ioCfg = IO_CONFIG(
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
|
|
||||||
GPIO_SPEED_FREQ_HIGH,
|
|
||||||
((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULLDOWN : GPIO_PULLUP
|
|
||||||
);
|
|
||||||
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
|
|
||||||
} else {
|
|
||||||
if ((mode & MODE_TX) && txIO) {
|
|
||||||
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
|
|
||||||
|
|
||||||
if (options & SERIAL_CHECK_TX) {
|
|
||||||
uartdev->txPinState = TX_PIN_ACTIVE;
|
|
||||||
// Switch TX to an input with pullup so it's state can be monitored
|
|
||||||
uartTxMonitor(s);
|
|
||||||
} else {
|
|
||||||
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode & MODE_RX) && rxIO) {
|
|
||||||
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
|
|
||||||
IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (!s->rxDMAResource)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
HAL_NVIC_SetPriority(hardware->rxIrq, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
|
|
||||||
HAL_NVIC_EnableIRQ(hardware->rxIrq);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // USE_UART
|
#endif // USE_UART
|
||||||
|
|
|
@ -38,12 +38,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -51,8 +45,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_UART6
|
#define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 6)
|
|
||||||
|
|
||||||
#define USE_INVERTER
|
#define USE_INVERTER
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
|
@ -34,18 +34,10 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART6
|
#define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 3)
|
|
||||||
|
|
||||||
#define USE_INVERTER
|
#define USE_INVERTER
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
|
@ -35,18 +35,10 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
// #define USE_UART6
|
// #define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 2)
|
|
||||||
|
|
||||||
#define USE_INVERTER
|
#define USE_INVERTER
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
|
@ -39,12 +39,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -54,8 +48,6 @@
|
||||||
#define USE_UART7
|
#define USE_UART7
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 8)
|
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
#define USE_SPI_DEVICE_2
|
#define USE_SPI_DEVICE_2
|
||||||
#define USE_SPI_DEVICE_3
|
#define USE_SPI_DEVICE_3
|
||||||
|
|
|
@ -34,12 +34,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -47,8 +41,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_UART6
|
#define USE_UART6
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 6)
|
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
#define USE_SPI_DEVICE_2
|
#define USE_SPI_DEVICE_2
|
||||||
#define USE_SPI_DEVICE_3
|
#define USE_SPI_DEVICE_3
|
||||||
|
|
|
@ -35,12 +35,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -48,8 +42,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 6)
|
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
#define USE_SPI_DEVICE_2
|
#define USE_SPI_DEVICE_2
|
||||||
#define USE_SPI_DEVICE_3
|
#define USE_SPI_DEVICE_3
|
||||||
|
|
|
@ -101,8 +101,6 @@
|
||||||
//#define USE_UART7
|
//#define USE_UART7
|
||||||
//#define USE_UART8
|
//#define USE_UART8
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 1)
|
|
||||||
|
|
||||||
//#define USE_SPI_DEVICE_1
|
//#define USE_SPI_DEVICE_1
|
||||||
//#define USE_SPI_DEVICE_2
|
//#define USE_SPI_DEVICE_2
|
||||||
//#define USE_SPI_DEVICE_3
|
//#define USE_SPI_DEVICE_3
|
||||||
|
|
|
@ -54,12 +54,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -71,8 +65,6 @@
|
||||||
#define USE_UART9
|
#define USE_UART9
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 10)
|
|
||||||
|
|
||||||
#define TARGET_IO_PORTA 0xffff
|
#define TARGET_IO_PORTA 0xffff
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
|
|
@ -63,8 +63,6 @@
|
||||||
#define USE_UART9
|
#define USE_UART9
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 10)
|
|
||||||
|
|
||||||
#define TARGET_IO_PORTA 0xffff
|
#define TARGET_IO_PORTA 0xffff
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
@ -83,12 +81,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_USB_DETECT
|
#define USE_USB_DETECT
|
||||||
|
|
||||||
#define USE_ESCSERIAL
|
#define USE_ESCSERIAL
|
||||||
|
|
|
@ -68,8 +68,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -82,8 +80,6 @@
|
||||||
#define USE_UART10
|
#define USE_UART10
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 11)
|
|
||||||
|
|
||||||
// Disable OCTOSPI pins PB2/CLK, PB6/NCS, PD11/IO0, PD12/IO1, PD13/IO3, PE2/IO2
|
// Disable OCTOSPI pins PB2/CLK, PB6/NCS, PD11/IO0, PD12/IO1, PD13/IO3, PE2/IO2
|
||||||
// PE7/IO4, PE8/IO5, PE9/IO6, PE10/IO7
|
// PE7/IO4, PE8/IO5, PE9/IO6, PE10/IO7
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -51,8 +45,6 @@
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 9)
|
|
||||||
|
|
||||||
#define USE_SPI_DEVICE_1
|
#define USE_SPI_DEVICE_1
|
||||||
#define USE_SPI_DEVICE_2
|
#define USE_SPI_DEVICE_2
|
||||||
#define USE_SPI_DEVICE_3
|
#define USE_SPI_DEVICE_3
|
||||||
|
|
|
@ -68,12 +68,6 @@
|
||||||
|
|
||||||
#define USE_VCP
|
#define USE_VCP
|
||||||
|
|
||||||
#ifdef USE_SOFTSERIAL
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 3
|
|
||||||
#else
|
|
||||||
#define UNIFIED_SERIAL_PORT_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USE_UART1
|
#define USE_UART1
|
||||||
#define USE_UART2
|
#define USE_UART2
|
||||||
#define USE_UART3
|
#define USE_UART3
|
||||||
|
@ -84,8 +78,6 @@
|
||||||
#define USE_UART8
|
#define USE_UART8
|
||||||
#define USE_LPUART1
|
#define USE_LPUART1
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT (UNIFIED_SERIAL_PORT_COUNT + 9)
|
|
||||||
|
|
||||||
#define TARGET_IO_PORTA 0xffff
|
#define TARGET_IO_PORTA 0xffff
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
|
|
@ -117,9 +117,11 @@ cli_unittest_SRC := \
|
||||||
$(USER_DIR)/common/gps_conversion.c \
|
$(USER_DIR)/common/gps_conversion.c \
|
||||||
$(USER_DIR)/config/feature.c \
|
$(USER_DIR)/config/feature.c \
|
||||||
$(USER_DIR)/io/gps.c \
|
$(USER_DIR)/io/gps.c \
|
||||||
|
$(USER_DIR)/io/serial_resource.c \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
$(USER_DIR)/fc/runtime_config.c \
|
$(USER_DIR)/fc/runtime_config.c \
|
||||||
$(USER_DIR)/drivers/serial.c \
|
$(USER_DIR)/drivers/serial.c \
|
||||||
|
$(USER_DIR)/drivers/serial_impl.c \
|
||||||
$(USER_DIR)/common/typeconversion.c
|
$(USER_DIR)/common/typeconversion.c
|
||||||
|
|
||||||
cli_unittest_DEFINES := \
|
cli_unittest_DEFINES := \
|
||||||
|
@ -175,6 +177,7 @@ gps_conversion_unittest_SRC := \
|
||||||
|
|
||||||
io_serial_unittest_SRC := \
|
io_serial_unittest_SRC := \
|
||||||
$(USER_DIR)/io/serial.c \
|
$(USER_DIR)/io/serial.c \
|
||||||
|
$(USER_DIR)/io/serial_resource.c \
|
||||||
$(USER_DIR)/drivers/serial_pinconfig.c
|
$(USER_DIR)/drivers/serial_pinconfig.c
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,6 +235,7 @@ link_quality_unittest_SRC := \
|
||||||
$(USER_DIR)/common/vector.c \
|
$(USER_DIR)/common/vector.c \
|
||||||
$(USER_DIR)/drivers/display.c \
|
$(USER_DIR)/drivers/display.c \
|
||||||
$(USER_DIR)/drivers/serial.c \
|
$(USER_DIR)/drivers/serial.c \
|
||||||
|
$(USER_DIR)/drivers/serial_impl.c \
|
||||||
$(USER_DIR)/fc/rc_modes.c \
|
$(USER_DIR)/fc/rc_modes.c \
|
||||||
$(USER_DIR)/fc/runtime_config.c \
|
$(USER_DIR)/fc/runtime_config.c \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
|
@ -267,7 +271,9 @@ rx_crsf_unittest_SRC := \
|
||||||
$(USER_DIR)/common/printf.c \
|
$(USER_DIR)/common/printf.c \
|
||||||
$(USER_DIR)/common/typeconversion.c \
|
$(USER_DIR)/common/typeconversion.c \
|
||||||
$(USER_DIR)/common/streambuf.c \
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/drivers/serial.c
|
$(USER_DIR)/drivers/serial.c \
|
||||||
|
$(USER_DIR)/drivers/serial_impl.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rx_ibus_unittest_SRC := \
|
rx_ibus_unittest_SRC := \
|
||||||
|
@ -347,6 +353,7 @@ telemetry_crsf_msp_unittest_SRC := \
|
||||||
$(USER_DIR)/common/printf.c \
|
$(USER_DIR)/common/printf.c \
|
||||||
$(USER_DIR)/common/streambuf.c \
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/drivers/serial.c \
|
$(USER_DIR)/drivers/serial.c \
|
||||||
|
$(USER_DIR)/drivers/serial_impl.c \
|
||||||
$(USER_DIR)/common/typeconversion.c \
|
$(USER_DIR)/common/typeconversion.c \
|
||||||
$(USER_DIR)/telemetry/crsf.c \
|
$(USER_DIR)/telemetry/crsf.c \
|
||||||
$(USER_DIR)/common/gps_conversion.c \
|
$(USER_DIR)/common/gps_conversion.c \
|
||||||
|
@ -359,6 +366,7 @@ telemetry_crsf_msp_unittest_DEFINES := \
|
||||||
|
|
||||||
telemetry_hott_unittest_SRC := \
|
telemetry_hott_unittest_SRC := \
|
||||||
$(USER_DIR)/telemetry/hott.c \
|
$(USER_DIR)/telemetry/hott.c \
|
||||||
|
$(USER_DIR)/io/serial_resource.c \
|
||||||
$(USER_DIR)/common/gps_conversion.c
|
$(USER_DIR)/common/gps_conversion.c
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,11 +70,11 @@ extern "C" {
|
||||||
|
|
||||||
serialPort_t *usbVcpOpen(void) { return NULL; }
|
serialPort_t *usbVcpOpen(void) { return NULL; }
|
||||||
|
|
||||||
serialPort_t *uartOpen(UARTDevice_e, serialReceiveCallbackPtr, void *, uint32_t, portMode_e, portOptions_e) {
|
serialPort_t *uartOpen(serialPortIdentifier_e, serialReceiveCallbackPtr, void *, uint32_t, portMode_e, portOptions_e) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPort_t *openSoftSerial(softSerialPortIndex_e, serialReceiveCallbackPtr, void *, uint32_t, portMode_e, portOptions_e) {
|
serialPort_t *softSerialOpen(serialPortIdentifier_e, serialReceiveCallbackPtr, void *, uint32_t, portMode_e, portOptions_e) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@
|
||||||
#define USE_UART5
|
#define USE_UART5
|
||||||
#define USE_SOFTSERIAL
|
#define USE_SOFTSERIAL
|
||||||
|
|
||||||
#define SERIAL_PORT_COUNT 8
|
|
||||||
|
|
||||||
#define DEFAULT_AUX_CHANNEL_COUNT MAX_AUX_CHANNEL_COUNT
|
#define DEFAULT_AUX_CHANNEL_COUNT MAX_AUX_CHANNEL_COUNT
|
||||||
#define MAX_SIMULTANEOUS_ADJUSTMENT_COUNT 6 // needed for unittest
|
#define MAX_SIMULTANEOUS_ADJUSTMENT_COUNT 6 // needed for unittest
|
||||||
|
@ -79,3 +78,4 @@
|
||||||
#define TARGET_IO_PORTB 0xffff
|
#define TARGET_IO_PORTB 0xffff
|
||||||
#define TARGET_IO_PORTC 0xffff
|
#define TARGET_IO_PORTC 0xffff
|
||||||
|
|
||||||
|
#include "target/serial_post.h"
|
||||||
|
|
94
src/utils/gen-serial-j2.py
Normal file
94
src/utils/gen-serial-j2.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
import jinja2
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
# generate normalization preprocessor file for serial ports
|
||||||
|
|
||||||
|
# configuration for template generation
|
||||||
|
serials = {
|
||||||
|
"UART": {"ids": [i + 1 for i in range(10)],
|
||||||
|
"inverter": True,
|
||||||
|
},
|
||||||
|
"LPUART": {"ids": [1],
|
||||||
|
"depends": {"UART"},
|
||||||
|
# "inverter": True, # TODO: old code compatibility only, disabled
|
||||||
|
},
|
||||||
|
"SOFTSERIAL": {"ids": [i + 1 for i in range(2)],
|
||||||
|
"use_enables_all": True,
|
||||||
|
"force_continuous": True,
|
||||||
|
},
|
||||||
|
"VCP": {"singleton": True,
|
||||||
|
"no_pins": True}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flatten_config(data):
|
||||||
|
flattened_list = []
|
||||||
|
for key, value in data.items():
|
||||||
|
flattened_dict = {'typ': key}
|
||||||
|
# Update this new dictionary with the inner dictionary's items
|
||||||
|
flattened_dict.update(value)
|
||||||
|
flattened_list.append(flattened_dict)
|
||||||
|
return flattened_list
|
||||||
|
|
||||||
|
def pprint_filter(value, indent=4):
|
||||||
|
return pprint.pformat(value, indent=indent)
|
||||||
|
|
||||||
|
def rdepends_filter(cfg, typ):
|
||||||
|
return list(set([ c['typ'] for c in cfg if typ in c['depends'] ]))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Setup Jinja2 environment
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# Set the template directory relative to the current script
|
||||||
|
template_dir = os.path.join(current_dir, 'templates')
|
||||||
|
env = Environment(loader=FileSystemLoader(template_dir),
|
||||||
|
autoescape=True,
|
||||||
|
undefined=jinja2.StrictUndefined, # Throws an error on undefined variables
|
||||||
|
trim_blocks = True,
|
||||||
|
)
|
||||||
|
env.filters['pprint'] = pprint_filter
|
||||||
|
env.filters['zip'] = zip
|
||||||
|
env.filters['rdepends'] = rdepends_filter
|
||||||
|
template = env.get_template('serial_post.h')
|
||||||
|
|
||||||
|
# Read license file
|
||||||
|
license_path = 'DEFAULT_LICENSE.md'
|
||||||
|
with open(license_path, 'r') as file:
|
||||||
|
t_license = file.read()
|
||||||
|
|
||||||
|
context = {}
|
||||||
|
context['license'] = t_license
|
||||||
|
context['date_generated'] = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
context['user_config'] = serials
|
||||||
|
config = flatten_config(serials)
|
||||||
|
context['config'] = config
|
||||||
|
|
||||||
|
for cfg in config:
|
||||||
|
singleton = cfg.setdefault('singleton', False)
|
||||||
|
no_pins = cfg.setdefault('no_pins', False)
|
||||||
|
inverter = cfg.setdefault('inverter', False)
|
||||||
|
cfg.setdefault("use_enables_all", False)
|
||||||
|
cfg.setdefault("force_continuous", False)
|
||||||
|
cfg.setdefault("depends", {})
|
||||||
|
typ = cfg['typ']
|
||||||
|
if singleton:
|
||||||
|
cfg['ports']= [ f"{typ}" ]
|
||||||
|
else:
|
||||||
|
cfg['ports'] = [ f"{typ}{i}" for i in cfg["ids"] ]
|
||||||
|
|
||||||
|
# Render the template with the license content
|
||||||
|
output = template.render(**context)
|
||||||
|
|
||||||
|
if False:
|
||||||
|
# Output or save to a file
|
||||||
|
output_path = './src/main/target/serial_post.h'
|
||||||
|
with open(output_path, 'w') as file:
|
||||||
|
file.write(output)
|
||||||
|
print(f"Generated file saved to {output_path}")
|
||||||
|
else:
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
118
src/utils/templates/serial_post.h
Normal file
118
src/utils/templates/serial_post.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
{# serial_post.h #}
|
||||||
|
{# DEFAULT_LICENCE.md is used #}
|
||||||
|
{{ license|safe }}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{# Start with generated warning. It you want to change something, edit this file #}
|
||||||
|
This file is automatically generated by src/utils/gen-serial.py script from src/utils/templates/serial_post.h jinja2 template.
|
||||||
|
Do not modify this file directly, your changes will be eventually lost.
|
||||||
|
See template{# THIS #} file for aditional documentation.
|
||||||
|
|
||||||
|
To generate this file again, run
|
||||||
|
> python ./src/utils/gen-serial-j2.py > ./src/main/target/serial_post.h
|
||||||
|
in Betaflight topmost directory.
|
||||||
|
|
||||||
|
This include will provide following defines:
|
||||||
|
SERIAL_<type><n>_USED 0/1 - always defined, value depends on target configuration
|
||||||
|
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>1 is BIT(0)
|
||||||
|
SERIAL_<type>_COUNT - number of enabled ports of given type
|
||||||
|
SERIAL_<type>_MAX - <index of highest used port> + 1, 0 when no port is enabled
|
||||||
|
|
||||||
|
All <type><n>_(RX|TX)_PINS are normalized too:
|
||||||
|
- if port is enabled, both will be defined (possibly as NONE)
|
||||||
|
- if port is not enable, both will be undefined, possibly with warning
|
||||||
|
- pass -DWARN_UNUSED_SERIAL_PORT to compiler to check pin defined without corresponding port being enabled.
|
||||||
|
|
||||||
|
{# add some usefull info #}
|
||||||
|
Generated on {{ date_generated }}
|
||||||
|
|
||||||
|
Configuration used:
|
||||||
|
{# TODO - maybe store configuration in this file, not Python one #}
|
||||||
|
{# TODO - pretty is not enough pretty #}
|
||||||
|
{{ user_config|pprint|safe }}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/utils.h" // BIT, LOG2
|
||||||
|
{# config array is passed to this script. It is flattened version of user_config, with default fileld in #}
|
||||||
|
{% for cfg in config %}
|
||||||
|
|
||||||
|
/**** {{ cfg.typ }} *****/
|
||||||
|
{# use_enables_all - USE_<type> enables all ports of this type #}
|
||||||
|
{% if cfg.use_enables_all %}
|
||||||
|
#if defined(USE_{{cfg.typ}})
|
||||||
|
{% for port in cfg.ports %}
|
||||||
|
# if !defined(USE_{{port}})
|
||||||
|
# define USE_{{port}}
|
||||||
|
# endif
|
||||||
|
{% endfor %}
|
||||||
|
#endif
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# USE_<port> - SERIAL_<port>_USED 0/1 #}
|
||||||
|
{% for port in cfg.ports %}
|
||||||
|
#if defined(USE_{{port}})
|
||||||
|
# define SERIAL_{{port}}_USED 1
|
||||||
|
#else
|
||||||
|
# define SERIAL_{{port}}_USED 0
|
||||||
|
#endif
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{# SERIAL_<port>_* summary macros #}
|
||||||
|
{% if not cfg.singleton %}
|
||||||
|
{% set pipe = joiner(' | ') %}
|
||||||
|
#define SERIAL_{{ cfg.typ }}_MASK ({% for port, i in cfg.ports|zip(cfg.ids) %}{{ pipe() }}(SERIAL_{{ port }}_USED * BIT({{ i }} - 1)){% endfor %})
|
||||||
|
{% else %}
|
||||||
|
{# one port without number is defined #}
|
||||||
|
// set one bit if port is enabled for consistency
|
||||||
|
#define SERIAL_{{ cfg.typ }}_MASK (SERIAL_{{ cfg.ports[0] }}_USED * BIT(0))
|
||||||
|
{% endif %}
|
||||||
|
{% set plus = joiner(' + ') %}
|
||||||
|
#define SERIAL_{{ cfg.typ }}_COUNT ({% for port in cfg.ports %}{{ plus() }}SERIAL_{{ port }}_USED{% endfor %})
|
||||||
|
{# LOG2 is simpler than chaining MAX(SERIAL_x1_USED * 1, MAX(SERIAL_x2_USED * 2, ... #}
|
||||||
|
// 0 if no port is defined
|
||||||
|
#define SERIAL_{{ cfg.typ }}_MAX (SERIAL_{{cfg.typ}}_MASK ? LOG2(SERIAL_{{cfg.typ}}_MASK) + 1 : 0)
|
||||||
|
|
||||||
|
{# for softserial, we don't want softserial2 only #}
|
||||||
|
{% if cfg.force_continuous %}
|
||||||
|
#if SERIAL_{{cfg.typ}}_COUNT != SERIAL_{{cfg.typ}}_MAX
|
||||||
|
# error {{cfg.typ}} ports must start with {{cfg.typ}}1 and be continuous
|
||||||
|
#endif
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# backward compatibility, code did set USE_INVERTER this way. It must be done before normalizing to NONE #}
|
||||||
|
{% if cfg.inverter %}
|
||||||
|
// enable USE_INVERTED first, before normalization
|
||||||
|
{% set pipe2 = joiner(' || ') %}
|
||||||
|
#if !defined(USE_INVERTER) && ({% for port in cfg.ports %}{{ pipe2() }}INVERTER_PIN_{{ port }}{% endfor %})
|
||||||
|
# define USE_INVERTER
|
||||||
|
#endif
|
||||||
|
{% endif %}
|
||||||
|
{# no pins for VCP port #}
|
||||||
|
{% if not cfg.no_pins %}
|
||||||
|
// Normalize {{cfg.typ}} TX/RX{{ "/INVERTER" if cfg.inverter else "" }}
|
||||||
|
{% for port in cfg.ports %}
|
||||||
|
{% set pins = [ port ~ '_RX_PIN', port ~ '_TX_PIN' ] + (['INVERTER_PIN_' ~ port] if cfg.inverter else []) %}
|
||||||
|
{% for pin in pins %}
|
||||||
|
#if SERIAL_{{port}}_USED && !defined({{pin}})
|
||||||
|
# define {{ pin }} NONE
|
||||||
|
#endif
|
||||||
|
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_{{ port }}_USED && defined({{ pin }})
|
||||||
|
# warning "{{ pin }} is defined but {{ port }} is not enabled"
|
||||||
|
#endif
|
||||||
|
#if !SERIAL_{{ port }}_USED && defined({{ pin }})
|
||||||
|
# undef {{ pin }}
|
||||||
|
#endif
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
// normalize USE_x after all ports are enumerated (x_COUNT of dependencies must be available)
|
||||||
|
{% for cfg in config %}
|
||||||
|
{% set depends = [cfg.typ] + config|rdepends(cfg.typ) %}
|
||||||
|
{% set pipe2 = joiner(' || ') %}
|
||||||
|
#if !defined(USE_{{cfg.typ}}) && ({% for typ in depends %}{{ pipe2() }}SERIAL_{{ typ }}_COUNT{% endfor %})
|
||||||
|
# define USE_{{cfg.typ}}
|
||||||
|
#endif
|
||||||
|
{% endfor %}
|
Loading…
Add table
Add a link
Reference in a new issue