Softserial with monotimer and bidir

This commit is contained in:
jflyper 2017-02-04 21:43:41 +09:00 committed by borisbstyle
parent b2c32b84e3
commit 97b5dbc386
11 changed files with 450 additions and 100 deletions

View File

@ -34,6 +34,7 @@
#include "drivers/light_led.h"
#include "drivers/flash.h"
#include "drivers/display.h"
#include "drivers/serial.h"
#include "fc/rc_controls.h"
@ -86,6 +87,7 @@
#define mixerConfig(x) (&masterConfig.mixerConfig)
#define airplaneConfig(x) (&masterConfig.airplaneConfig)
#define failsafeConfig(x) (&masterConfig.failsafeConfig)
#define serialPinConfig(x) (&masterConfig.serialPinConfig)
#define serialConfig(x) (&masterConfig.serialConfig)
#define telemetryConfig(x) (&masterConfig.telemetryConfig)
#define ibusTelemetryConfig(x) (&masterConfig.telemetryConfig)
@ -173,6 +175,7 @@ typedef struct master_s {
airplaneConfig_t airplaneConfig;
failsafeConfig_t failsafeConfig;
serialPinConfig_t serialPinConfig;
serialConfig_t serialConfig;
telemetryConfig_t telemetryConfig;

View File

@ -17,6 +17,8 @@
#pragma once
#include "drivers/io.h"
typedef enum portMode_t {
MODE_RX = 1 << 0,
MODE_TX = 1 << 1,
@ -68,6 +70,21 @@ typedef struct serialPort_s {
serialReceiveCallbackPtr rxCallback;
} serialPort_t;
#if defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)
# ifdef USE_SOFTSERIAL2
# define SERIAL_PORT_MAX_INDEX (RESOURCE_SOFT_OFFSET + 2)
# else
# define SERIAL_PORT_MAX_INDEX (RESOURCE_SOFT_OFFSET + 1)
# endif
#else
# define SERIAL_PORT_MAX_INDEX RESOURCE_SOFT_OFFSET
#endif
typedef struct serialPinConfig_s {
ioTag_t ioTagTx[SERIAL_PORT_MAX_INDEX];
ioTag_t ioTagRx[SERIAL_PORT_MAX_INDEX];
} serialPinConfig_t;
struct serialPortVTable {
void (*serialWrite)(serialPort_t *instance, uint8_t ch);

View File

@ -25,8 +25,12 @@
#include "build/build_config.h"
#include "build/atomic.h"
#include "build/debug.h"
#include "common/utils.h"
#include "config/config_master.h"
#include "nvic.h"
#include "system.h"
#include "io.h"
@ -44,21 +48,29 @@
#define MAX_SOFTSERIAL_PORTS 1
#endif
typedef enum {
TIMER_MODE_SINGLE,
TIMER_MODE_DUAL,
} timerMode_e;
typedef struct softSerial_s {
serialPort_t port;
IO_t rxIO;
IO_t txIO;
const timerHardware_t *rxTimerHardware;
volatile uint8_t rxBuffer[SOFTSERIAL_BUFFER_SIZE];
const timerHardware_t *txTimerHardware;
const timerHardware_t *timerHardware;
const timerHardware_t *exTimerHardware;
uint32_t ccEnableBit;
volatile uint8_t rxBuffer[SOFTSERIAL_BUFFER_SIZE];
volatile uint8_t txBuffer[SOFTSERIAL_BUFFER_SIZE];
uint8_t isSearchingForStartBit;
uint8_t rxBitIndex;
uint8_t rxLastLeadingEdgeAtBitIndex;
uint8_t rxEdge;
uint8_t rxActive;
uint8_t isTransmittingData;
int8_t bitsLeftToTransmit;
@ -70,23 +82,20 @@ typedef struct softSerial_s {
uint16_t receiveErrors;
uint8_t softSerialPortIndex;
timerMode_e timerMode;
timerCCHandlerRec_t timerCb;
timerOvrHandlerRec_t overCb;
timerCCHandlerRec_t edgeCb;
} softSerial_t;
extern timerHardware_t* serialTimerHardware;
extern softSerial_t softSerialPorts[];
static const struct serialPortVTable softSerialVTable; // Forward
extern const struct serialPortVTable softSerialVTable[];
static softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS];
softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS];
void onSerialTimer(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture);
void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
void setTxSignal(softSerial_t *softSerial, uint8_t state)
static void setTxSignal(softSerial_t *softSerial, uint8_t state)
{
if (softSerial->port.options & SERIAL_INVERTED) {
state = !state;
@ -99,20 +108,83 @@ void setTxSignal(softSerial_t *softSerial, uint8_t state)
}
}
void serialInputPortConfig(ioTag_t pin, uint8_t portIndex)
// XXX CCEnableBit: Compute CCxE bit.
// XXX (Note: timer.c:timerChICPolarity() uses "TIM_CCER_CC1P << timHw->channel".)
static uint32_t CCEnableBit(int channel)
{
IOInit(IOGetByTag(pin), OWNER_SERIAL_RX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET);
#ifdef STM32F1
IOConfigGPIO(IOGetByTag(pin), IOCFG_IPU);
uint32_t bit;
#if defined(STM32F7)
switch (channel) {
case TIM_CHANNEL_1:
bit = TIM_CCER_CC1E;
break;
case TIM_CHANNEL_2:
bit = TIM_CCER_CC2E;
break;
case TIM_CHANNEL_3:
bit = TIM_CCER_CC3E;
break;
case TIM_CHANNEL_4:
bit = TIM_CCER_CC4E;
break;
}
#else
IOConfigGPIO(IOGetByTag(pin), IOCFG_AF_PP_UP);
switch (channel) {
case TIM_Channel_1:
bit = TIM_CCER_CC1E;
break;
case TIM_Channel_2:
bit = TIM_CCER_CC2E;
break;
case TIM_Channel_3:
bit = TIM_CCER_CC3E;
break;
case TIM_Channel_4:
bit = TIM_CCER_CC4E;
break;
}
#endif
return bit;
}
static void serialOutputPortConfig(ioTag_t pin, uint8_t portIndex)
static void serialInputPortActivate(softSerial_t *softSerial)
{
IOInit(IOGetByTag(pin), OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET);
IOConfigGPIO(IOGetByTag(pin), IOCFG_OUT_PP);
softSerial->rxActive = true;
#ifdef STM32F1
IOConfigGPIO(softSerial->rxIO, IOCFG_IPU);
#else
IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_UP);
#endif
softSerial->isSearchingForStartBit = true;
softSerial->rxBitIndex = 0;
// Enable input capture
softSerial->timerHardware->tim->CCER |= softSerial->ccEnableBit;
}
static void serialInputPortDeActivate(softSerial_t *softSerial)
{
// Disable input capture
softSerial->timerHardware->tim->CCER &= ~softSerial->ccEnableBit;
IOConfigGPIO(softSerial->rxIO, IOCFG_IN_FLOATING);
softSerial->rxActive = false;
}
static void serialOutputPortActivate(softSerial_t *softSerial)
{
IOConfigGPIO(softSerial->txIO, IOCFG_OUT_PP);
}
static void serialOutputPortDeActivate(softSerial_t *softSerial)
{
IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING);
}
static bool isTimerPeriodTooLarge(uint32_t timerPeriod)
@ -120,10 +192,12 @@ static bool isTimerPeriodTooLarge(uint32_t timerPeriod)
return timerPeriod > 0xFFFF;
}
static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference, uint32_t baud)
static void serialTimerConfigureTimebase(const timerHardware_t *timerHardwarePtr, uint32_t baud)
{
uint32_t clock = SystemCoreClock;
uint32_t baseClock = SystemCoreClock / timerClockDivisor(timerHardwarePtr->tim);
uint32_t clock = baseClock;
uint32_t timerPeriod;
do {
timerPeriod = clock / baud;
if (isTimerPeriodTooLarge(timerPeriod)) {
@ -136,10 +210,9 @@ static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t
}
} while (isTimerPeriodTooLarge(timerPeriod));
uint8_t mhz = SystemCoreClock / 1000000;
uint8_t mhz = baseClock / 1000000;
timerConfigure(timerHardwarePtr, timerPeriod, mhz);
timerChCCHandlerInit(&softSerialPorts[reference].timerCb, onSerialTimer);
timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].timerCb, NULL);
}
static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
@ -156,14 +229,6 @@ static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
TIM_ICInit(tim, &TIM_ICInitStructure);
}
static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference, portOptions_t options)
{
// start bit is usually a FALLING signal
serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
timerChCCHandlerInit(&softSerialPorts[reference].edgeCb, onSerialRxPinChange);
timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].edgeCb, NULL);
}
static void resetBuffers(softSerial_t *softSerial)
{
softSerial->port.rxBufferSize = SOFTSERIAL_BUFFER_SIZE;
@ -177,71 +242,131 @@ static void resetBuffers(softSerial_t *softSerial)
softSerial->port.txBufferHead = 0;
}
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portOptions_t options)
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portMode_t mode, portOptions_t options)
{
softSerial_t *softSerial = &(softSerialPorts[portIndex]);
#ifdef USE_SOFTSERIAL1
if (portIndex == SOFTSERIAL1) {
softSerial->rxTimerHardware = &(timerHardware[SOFTSERIAL_1_TIMER_RX_HARDWARE]);
softSerial->txTimerHardware = &(timerHardware[SOFTSERIAL_1_TIMER_TX_HARDWARE]);
}
#endif
int pinCfgIndex = portIndex + RESOURCE_SOFT_OFFSET;
#ifdef USE_SOFTSERIAL2
if (portIndex == SOFTSERIAL2) {
softSerial->rxTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_RX_HARDWARE]);
softSerial->txTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_TX_HARDWARE]);
}
#endif
ioTag_t tagRx = serialPinConfig()->ioTagRx[pinCfgIndex];
ioTag_t tagTx = serialPinConfig()->ioTagTx[pinCfgIndex];
softSerial->port.vTable = softSerialVTable;
const timerHardware_t *timerRx = timerGetByTag(tagRx, TIM_USE_ANY);
const timerHardware_t *timerTx = timerGetByTag(tagTx, TIM_USE_ANY);
IO_t rxIO = IOGetByTag(tagRx);
IO_t txIO = IOGetByTag(tagTx);
if (options & SERIAL_BIDIR) {
// 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,
// and this pin must have a timer.
if (!timerTx)
return NULL;
softSerial->timerHardware = timerTx;
softSerial->txIO = txIO;
softSerial->rxIO = txIO;
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET);
} else {
if (mode & MODE_RX) {
// Need a pin & a timer on RX
if (!(tagRx && timerRx))
return NULL;
softSerial->rxIO = rxIO;
softSerial->timerHardware = timerRx;
IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET);
}
if (mode & MODE_TX) {
// Need a pin on TX
if (!tagTx)
return NULL;
softSerial->txIO = txIO;
softSerial->exTimerHardware = timerTx;
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET);
}
}
softSerial->ccEnableBit = CCEnableBit(softSerial->timerHardware->channel);
//debug[2] = softSerial->ccEnableBit;
softSerial->port.vTable = &softSerialVTable;
softSerial->port.baudRate = baud;
softSerial->port.mode = MODE_RXTX;
softSerial->port.mode = mode;
softSerial->port.options = options;
softSerial->port.rxCallback = rxCallback;
resetBuffers(softSerial);
softSerial->isTransmittingData = false;
softSerial->isSearchingForStartBit = true;
softSerial->rxBitIndex = 0;
softSerial->softSerialPortIndex = portIndex;
softSerial->transmissionErrors = 0;
softSerial->receiveErrors = 0;
softSerial->softSerialPortIndex = portIndex;
softSerial->rxActive = false;
softSerial->isTransmittingData = false;
softSerial->txIO = IOGetByTag(softSerial->txTimerHardware->tag);
serialOutputPortConfig(softSerial->txTimerHardware->tag, portIndex);
// Configure master timer (on RX); time base and input capture
softSerial->rxIO = IOGetByTag(softSerial->rxTimerHardware->tag);
serialInputPortConfig(softSerial->rxTimerHardware->tag, portIndex);
serialTimerConfigureTimebase(softSerial->timerHardware, baud);
serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
// Initialize callbacks
timerChCCHandlerInit(&softSerial->edgeCb, onSerialRxPinChange);
timerChOvrHandlerInit(&softSerial->overCb, onSerialTimerOverflow);
// Configure bit clock interrupt & handler.
// If we have an extra timer (on TX), it is initialized and configured
// for overflow interrupt.
// Receiver input capture is configured when input is activated.
if ((mode & MODE_TX) && softSerial->exTimerHardware && softSerial->exTimerHardware->tim != softSerial->timerHardware->tim) {
softSerial->timerMode = TIMER_MODE_DUAL;
serialTimerConfigureTimebase(softSerial->exTimerHardware, baud);
timerChConfigCallbacks(softSerial->exTimerHardware, NULL, &softSerial->overCb);
timerChConfigCallbacks(softSerial->timerHardware, &softSerial->edgeCb, NULL);
} else {
softSerial->timerMode = TIMER_MODE_SINGLE;
timerChConfigCallbacks(softSerial->timerHardware, &softSerial->edgeCb, &softSerial->overCb);
}
if (!(options & SERIAL_BIDIR)) {
serialOutputPortActivate(softSerial);
setTxSignal(softSerial, ENABLE);
delay(50);
}
serialTimerTxConfig(softSerial->txTimerHardware, portIndex, baud);
serialTimerRxConfig(softSerial->rxTimerHardware, portIndex, options);
serialInputPortActivate(softSerial);
return &softSerial->port;
}
/*********************************************/
//
// Serial engines
//
void processTxState(softSerial_t *softSerial)
{
uint8_t mask;
if (!softSerial->isTransmittingData) {
char byteToSend;
if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) {
// Transmit buffer empty.
// Start listening if not already in if half-duplex
if (!softSerial->rxActive && softSerial->port.options & SERIAL_BIDIR) {
serialOutputPortDeActivate(softSerial);
serialInputPortActivate(softSerial);
}
return;
}
// data to send
byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++];
char byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++];
if (softSerial->port.txBufferTail >= softSerial->port.txBufferSize) {
softSerial->port.txBufferTail = 0;
}
@ -251,6 +376,12 @@ void processTxState(softSerial_t *softSerial)
softSerial->bitsLeftToTransmit = TX_TOTAL_BITS;
softSerial->isTransmittingData = true;
if (softSerial->rxActive && (softSerial->port.options & SERIAL_BIDIR)) {
// Half-duplex: Deactivate receiver, activate transmitter
serialInputPortDeActivate(softSerial);
serialOutputPortActivate(softSerial);
}
return;
}
@ -288,9 +419,7 @@ void prepareForNextRxByte(softSerial_t *softSerial)
softSerial->isSearchingForStartBit = true;
if (softSerial->rxEdge == LEADING) {
softSerial->rxEdge = TRAILING;
serialICConfig(
softSerial->rxTimerHardware->tim,
softSerial->rxTimerHardware->channel,
serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel,
(softSerial->port.options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling
);
}
@ -347,18 +476,24 @@ void processRxState(softSerial_t *softSerial)
}
}
void onSerialTimer(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture)
{
UNUSED(capture);
softSerial_t *softSerial = container_of(cbRec, softSerial_t, timerCb);
//debug[0]++;
softSerial_t *softSerial = container_of(cbRec, softSerial_t, overCb);
if (softSerial->port.mode & MODE_TX)
processTxState(softSerial);
if (softSerial->port.mode & MODE_RX)
processRxState(softSerial);
}
void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
{
UNUSED(capture);
//debug[1]++;
softSerial_t *softSerial = container_of(cbRec, softSerial_t, edgeCb);
bool inverted = softSerial->port.options & SERIAL_INVERTED;
@ -371,12 +506,12 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
// synchronise bit counter
// FIXME this reduces functionality somewhat as receiving breaks concurrent transmission on all ports because
// the next callback to the onSerialTimer will happen too early causing transmission errors.
TIM_SetCounter(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->tim->ARR / 2);
if (softSerial->isTransmittingData) {
TIM_SetCounter(softSerial->timerHardware->tim, softSerial->timerHardware->tim->ARR / 2);
if ((softSerial->timerMode != TIMER_MODE_DUAL) && softSerial->isTransmittingData) {
softSerial->transmissionErrors++;
}
serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
softSerial->rxEdge = LEADING;
softSerial->rxBitIndex = 0;
@ -394,13 +529,17 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
if (softSerial->rxEdge == TRAILING) {
softSerial->rxEdge = LEADING;
serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
} else {
softSerial->rxEdge = TRAILING;
serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
}
}
//
// Standard serial driver API
//
uint32_t softSerialRxBytesWaiting(const serialPort_t *instance)
{
if ((instance->mode & MODE_RX) == 0) {
@ -455,7 +594,10 @@ void softSerialWriteByte(serialPort_t *s, uint8_t ch)
void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate)
{
softSerial_t *softSerial = (softSerial_t *)s;
openSoftSerial(softSerial->softSerialPortIndex, s->rxCallback, baudRate, softSerial->port.options);
softSerial->port.baudRate = baudRate;
serialTimerConfigureTimebase(softSerial->timerHardware, baudRate);
}
void softSerialSetMode(serialPort_t *instance, portMode_t mode)
@ -468,8 +610,7 @@ bool isSoftSerialTransmitBufferEmpty(const serialPort_t *instance)
return instance->txBufferHead == instance->txBufferTail;
}
const struct serialPortVTable softSerialVTable[] = {
{
static const struct serialPortVTable softSerialVTable = {
.serialWrite = softSerialWriteByte,
.serialTotalRxWaiting = softSerialRxBytesWaiting,
.serialTotalTxFree = softSerialTxBytesFree,
@ -480,7 +621,6 @@ const struct serialPortVTable softSerialVTable[] = {
.writeBuf = NULL,
.beginWrite = NULL,
.endWrite = NULL
}
};
#endif

View File

@ -24,7 +24,7 @@ typedef enum {
SOFTSERIAL2
} softSerialPortIndex_e;
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portOptions_t options);
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portMode_t mode, portOptions_t options);
// serialPort API
void softSerialWriteByte(serialPort_t *instance, uint8_t ch);

View File

@ -3342,6 +3342,8 @@ const cliResourceValue_t resourceTable[] = {
#ifdef LED_STRIP
{ OWNER_LED_STRIP, &ledStripConfig()->ioTag, 0 },
#endif
{ OWNER_SERIAL_TX, &serialPinConfig()->ioTagTx[0], SERIAL_PORT_MAX_INDEX },
{ OWNER_SERIAL_RX, &serialPinConfig()->ioTagRx[0], SERIAL_PORT_MAX_INDEX },
};
static void printResource(uint8_t dumpMask, const master_t *defaultConfig)

View File

@ -428,6 +428,175 @@ void resetBatteryConfig(batteryConfig_t *batteryConfig)
batteryConfig->consumptionWarningPercentage = 10;
}
// Default pin (NONE).
// XXX Does this mess belong here???
#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
#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
#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
#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
#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
#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
#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
#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
#endif
#ifdef USE_SOFTSERIAL1
# if !defined(SOFTSERIAL1_RX_PIN)
# define SOFTSERIAL1_RX_PIN NONE
# endif
# if !defined(SOFTSERIAL1_TX_PIN)
# define SOFTSERIAL1_TX_PIN NONE
# endif
#endif
#ifdef USE_SOFTSERIAL2
# if !defined(SOFTSERIAL2_RX_PIN)
# define SOFTSERIAL2_RX_PIN NONE
# endif
# if !defined(SOFTSERIAL2_TX_PIN)
# define SOFTSERIAL2_TX_PIN NONE
# endif
#endif
void resetSerialPinConfig(serialPinConfig_t *pSerialPinConfig)
{
for (int port = 0 ; port < SERIAL_PORT_MAX_INDEX ; port++) {
pSerialPinConfig->ioTagRx[port] = IO_TAG(NONE);
pSerialPinConfig->ioTagTx[port] = IO_TAG(NONE);
}
for (int index = 0 ; index < SERIAL_PORT_COUNT ; index++) {
switch (serialPortIdentifiers[index]) {
case SERIAL_PORT_USART1:
#ifdef USE_UART1
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART1)] = IO_TAG(UART1_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART1)] = IO_TAG(UART1_TX_PIN);
#endif
break;
case SERIAL_PORT_USART2:
#ifdef USE_UART2
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART2)] = IO_TAG(UART2_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART2)] = IO_TAG(UART2_TX_PIN);
#endif
break;
case SERIAL_PORT_USART3:
#ifdef USE_UART3
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART3)] = IO_TAG(UART3_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART3)] = IO_TAG(UART3_TX_PIN);
#endif
break;
case SERIAL_PORT_USART4:
#ifdef USE_UART4
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART4)] = IO_TAG(UART4_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART4)] = IO_TAG(UART4_TX_PIN);
#endif
break;
case SERIAL_PORT_USART5:
#ifdef USE_UART5
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART5)] = IO_TAG(UART5_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART5)] = IO_TAG(UART5_TX_PIN);
#endif
break;
case SERIAL_PORT_USART6:
#ifdef USE_UART6
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART6)] = IO_TAG(UART6_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART6)] = IO_TAG(UART6_TX_PIN);
#endif
break;
case SERIAL_PORT_USART7:
#ifdef USE_UART7
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART7)] = IO_TAG(UART7_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART7)] = IO_TAG(UART7_TX_PIN);
#endif
break;
case SERIAL_PORT_USART8:
#ifdef USE_UART8
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART8)] = IO_TAG(UART8_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART8)] = IO_TAG(UART8_TX_PIN);
#endif
break;
case SERIAL_PORT_SOFTSERIAL1:
#ifdef USE_SOFTSERIAL1
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL1)] = IO_TAG(SOFTSERIAL1_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL1)] = IO_TAG(SOFTSERIAL1_TX_PIN);
#endif
break;
case SERIAL_PORT_SOFTSERIAL2:
#ifdef USE_SOFTSERIAL2
pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL2)] = IO_TAG(SOFTSERIAL2_RX_PIN);
pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL2)] = IO_TAG(SOFTSERIAL2_TX_PIN);
#endif
break;
case SERIAL_PORT_USB_VCP:
break;
case SERIAL_PORT_NONE:
break;
}
}
}
#ifdef SWAP_SERIAL_PORT_0_AND_1_DEFAULTS
#define FIRST_PORT_INDEX 1
#define SECOND_PORT_INDEX 0
@ -747,6 +916,8 @@ void createDefaultConfig(master_t *config)
config->gpsConfig.autoBaud = GPS_AUTOBAUD_OFF;
#endif
resetSerialPinConfig(&config->serialPinConfig);
resetSerialConfig(&config->serialConfig);
resetProfile(&config->profile[0]);

View File

@ -352,14 +352,12 @@ serialPort_t *openSerialPort(
#endif
#ifdef USE_SOFTSERIAL1
case SERIAL_PORT_SOFTSERIAL1:
serialPort = openSoftSerial(SOFTSERIAL1, rxCallback, baudRate, options);
serialSetMode(serialPort, mode);
serialPort = openSoftSerial(SOFTSERIAL1, rxCallback, baudRate, mode, options);
break;
#endif
#ifdef USE_SOFTSERIAL2
case SERIAL_PORT_SOFTSERIAL2:
serialPort = openSoftSerial(SOFTSERIAL2, rxCallback, baudRate, options);
serialSetMode(serialPort, mode);
serialPort = openSoftSerial(SOFTSERIAL2, rxCallback, baudRate, mode, options);
break;
#endif
default:

View File

@ -81,6 +81,8 @@ typedef enum {
extern const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT];
#define SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(x) (((x) <= SERIAL_PORT_USART8) ? (x) : (RESOURCE_SOFT_OFFSET + ((x) - SERIAL_PORT_SOFTSERIAL1)))
//
// runtime
//

View File

@ -68,7 +68,8 @@
#define USE_UART1
#define USE_UART2
#define USE_UART3
#define SERIAL_PORT_COUNT 4
#define USE_SOFTSERIAL1
#define SERIAL_PORT_COUNT 5
#define UART1_TX_PIN PA9
#define UART1_RX_PIN PA10
@ -79,8 +80,9 @@
#define UART3_TX_PIN PB10 // PB10 (AF7)
#define UART3_RX_PIN PB11 // PB11 (AF7)
#define USE_I2C
#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA
#undef USE_I2C
//#define USE_I2C
//#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA
#define USE_ESCSERIAL
#define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1

View File

@ -125,11 +125,23 @@
#define UART6_RX_PIN PC7
#define UART6_TX_PIN PC6
#define USE_SOFTSERIAL1
//#define SOFTSERIAL1_RX_PIN PC8 // S5_IN (TIM8 CH3)
//#define SOFTSERIAL1_TX_PIN PC9 // S6_IN (TIM8 CH4)
#define USE_SOFTSERIAL2
// Special case of using different timers for RX and TX
//#define SOFTSERIAL2_RX_PIN PA1 // PWM5, LED_STRIP
//#define SOFTSERIAL2_TX_PIN PA8 // PWM6
// Experimental (untested)
//#define SOFTSERIAL2_RX_PIN PA8 // PWM6
//#define SOFTSERIAL2_TX_PIN PB15 // S2_IN
#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART3, USART6, SOFTSERIALx2
#define USE_ESCSERIAL
#define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1
#define SERIAL_PORT_COUNT 4 //VCP, USART1, USART3, USART6
#define USE_SPI
#define USE_SPI_DEVICE_1

View File

@ -157,7 +157,10 @@
#define UART6_RX_PIN PC7
#define UART6_TX_PIN PC6
#define SERIAL_PORT_COUNT 4 //VCP, USART1, USART3, USART6
#define USE_SOFTSERIAL1
#define USE_SOFTSERIAL2
#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART3, USART6, SOFTSERIALx2
#define USE_ESCSERIAL
#define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1