1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-17 05:15:25 +03:00

Ability to see how many Tx bytes are free in serial port buffer

This commit is contained in:
Nicholas Sherlock 2015-06-23 00:30:37 +12:00
parent d0b940bf75
commit 6e504ca52a
13 changed files with 90 additions and 22 deletions

View file

@ -40,9 +40,14 @@ void serialWrite(serialPort_t *instance, uint8_t ch)
instance->vTable->serialWrite(instance, ch); instance->vTable->serialWrite(instance, ch);
} }
uint8_t serialTotalBytesWaiting(serialPort_t *instance) uint8_t serialRxBytesWaiting(serialPort_t *instance)
{ {
return instance->vTable->serialTotalBytesWaiting(instance); return instance->vTable->serialTotalRxWaiting(instance);
}
uint8_t serialTxBytesFree(serialPort_t *instance)
{
return instance->vTable->serialTotalTxFree(instance);
} }
uint8_t serialRead(serialPort_t *instance) uint8_t serialRead(serialPort_t *instance)

View file

@ -62,7 +62,8 @@ typedef struct serialPort {
struct serialPortVTable { struct serialPortVTable {
void (*serialWrite)(serialPort_t *instance, uint8_t ch); void (*serialWrite)(serialPort_t *instance, uint8_t ch);
uint8_t (*serialTotalBytesWaiting)(serialPort_t *instance); uint8_t (*serialTotalRxWaiting)(serialPort_t *instance);
uint8_t (*serialTotalTxFree)(serialPort_t *instance);
uint8_t (*serialRead)(serialPort_t *instance); uint8_t (*serialRead)(serialPort_t *instance);
@ -75,7 +76,8 @@ struct serialPortVTable {
}; };
void serialWrite(serialPort_t *instance, uint8_t ch); void serialWrite(serialPort_t *instance, uint8_t ch);
uint8_t serialTotalBytesWaiting(serialPort_t *instance); uint8_t serialRxBytesWaiting(serialPort_t *instance);
uint8_t serialTxBytesFree(serialPort_t *instance);
uint8_t serialRead(serialPort_t *instance); uint8_t serialRead(serialPort_t *instance);
void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate); void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate);
void serialSetMode(serialPort_t *instance, portMode_t mode); void serialSetMode(serialPort_t *instance, portMode_t mode);

View file

@ -403,7 +403,7 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
} }
} }
uint8_t softSerialTotalBytesWaiting(serialPort_t *instance) uint8_t softSerialRxBytesWaiting(serialPort_t *instance)
{ {
if ((instance->mode & MODE_RX) == 0) { if ((instance->mode & MODE_RX) == 0) {
return 0; return 0;
@ -414,6 +414,19 @@ uint8_t softSerialTotalBytesWaiting(serialPort_t *instance)
return (s->port.rxBufferHead - s->port.rxBufferTail) & (s->port.rxBufferSize - 1); return (s->port.rxBufferHead - s->port.rxBufferTail) & (s->port.rxBufferSize - 1);
} }
uint8_t softSerialTxBytesFree(serialPort_t *instance)
{
if ((instance->mode & MODE_TX) == 0) {
return 0;
}
softSerial_t *s = (softSerial_t *)instance;
uint8_t bytesUsed = (s->port.txBufferHead - s->port.txBufferTail) & (s->port.txBufferSize - 1);
return (s->port.txBufferSize - 1) - bytesUsed;
}
uint8_t softSerialReadByte(serialPort_t *instance) uint8_t softSerialReadByte(serialPort_t *instance)
{ {
uint8_t ch; uint8_t ch;
@ -422,7 +435,7 @@ uint8_t softSerialReadByte(serialPort_t *instance)
return 0; return 0;
} }
if (softSerialTotalBytesWaiting(instance) == 0) { if (softSerialRxBytesWaiting(instance) == 0) {
return 0; return 0;
} }
@ -460,7 +473,8 @@ bool isSoftSerialTransmitBufferEmpty(serialPort_t *instance)
const struct serialPortVTable softSerialVTable[] = { const struct serialPortVTable softSerialVTable[] = {
{ {
softSerialWriteByte, softSerialWriteByte,
softSerialTotalBytesWaiting, softSerialRxBytesWaiting,
softSerialTxBytesFree,
softSerialReadByte, softSerialReadByte,
softSerialSetBaudRate, softSerialSetBaudRate,
isSoftSerialTransmitBufferEmpty, isSoftSerialTransmitBufferEmpty,

View file

@ -28,7 +28,8 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
// serialPort API // serialPort API
void softSerialWriteByte(serialPort_t *instance, uint8_t ch); void softSerialWriteByte(serialPort_t *instance, uint8_t ch);
uint8_t softSerialTotalBytesWaiting(serialPort_t *instance); uint8_t softSerialRxBytesWaiting(serialPort_t *instance);
uint8_t softSerialTxBytesFree(serialPort_t *instance);
uint8_t softSerialReadByte(serialPort_t *instance); uint8_t softSerialReadByte(serialPort_t *instance);
void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate); void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate);
bool isSoftSerialTransmitBufferEmpty(serialPort_t *s); bool isSoftSerialTransmitBufferEmpty(serialPort_t *s);

View file

@ -211,7 +211,7 @@ void uartStartTxDMA(uartPort_t *s)
DMA_Cmd(s->txDMAChannel, ENABLE); DMA_Cmd(s->txDMAChannel, ENABLE);
} }
uint8_t uartTotalBytesWaiting(serialPort_t *instance) uint8_t uartTotalRxBytesWaiting(serialPort_t *instance)
{ {
uartPort_t *s = (uartPort_t*)instance; uartPort_t *s = (uartPort_t*)instance;
if (s->rxDMAChannel) { if (s->rxDMAChannel) {
@ -230,6 +230,41 @@ uint8_t uartTotalBytesWaiting(serialPort_t *instance)
} }
} }
uint8_t uartTotalTxBytesFree(serialPort_t *instance)
{
uartPort_t *s = (uartPort_t*)instance;
uint32_t bytesUsed;
if (s->port.txBufferHead >= s->port.txBufferTail) {
bytesUsed = s->port.txBufferHead - s->port.txBufferTail;
} else {
bytesUsed = s->port.txBufferSize + s->port.txBufferHead - s->port.txBufferTail;
}
if (s->txDMAChannel) {
/*
* When we queue up a DMA request, we advance the Tx buffer tail before the transfer finishes, so we must add
* the remaining size of that in-progress transfer here instead:
*/
bytesUsed += s->txDMAChannel->CNDTR;
/*
* If the Tx buffer is being written to very quickly, we might have advanced the head into the buffer
* space occupied by the current DMA transfer. In that case the "bytesUsed" total will actually end up larger
* than the total Tx buffer size, because we'll end up transmitting the same buffer region twice. (So we'll be
* transmitting a garbage mixture of old and new bytes).
*
* Be kind to callers and pretend like our buffer can only ever be 100% full.
*/
if (bytesUsed >= s->port.txBufferSize - 1) {
return 0;
}
}
return (s->port.txBufferSize - 1) - bytesUsed;
}
bool isUartTransmitBufferEmpty(serialPort_t *instance) bool isUartTransmitBufferEmpty(serialPort_t *instance)
{ {
uartPort_t *s = (uartPort_t *)instance; uartPort_t *s = (uartPort_t *)instance;
@ -281,7 +316,8 @@ void uartWrite(serialPort_t *instance, uint8_t ch)
const struct serialPortVTable uartVTable[] = { const struct serialPortVTable uartVTable[] = {
{ {
uartWrite, uartWrite,
uartTotalBytesWaiting, uartTotalRxBytesWaiting,
uartTotalTxBytesFree,
uartRead, uartRead,
uartSetBaudRate, uartSetBaudRate,
isUartTransmitBufferEmpty, isUartTransmitBufferEmpty,

View file

@ -19,6 +19,10 @@
// Since serial ports can be used for any function these buffer sizes should be equal // 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. // 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 UART1_RX_BUFFER_SIZE 256 #define UART1_RX_BUFFER_SIZE 256
#define UART1_TX_BUFFER_SIZE 256 #define UART1_TX_BUFFER_SIZE 256
#define UART2_RX_BUFFER_SIZE 256 #define UART2_RX_BUFFER_SIZE 256
@ -48,7 +52,8 @@ serialPort_t *uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback,
// serialPort API // serialPort API
void uartWrite(serialPort_t *instance, uint8_t ch); void uartWrite(serialPort_t *instance, uint8_t ch);
uint8_t uartTotalBytesWaiting(serialPort_t *instance); uint8_t uartTotalRxBytesWaiting(serialPort_t *instance);
uint8_t uartTotalTxBytesFree(serialPort_t *instance);
uint8_t uartRead(serialPort_t *instance); uint8_t uartRead(serialPort_t *instance);
void uartSetBaudRate(serialPort_t *s, uint32_t baudRate); void uartSetBaudRate(serialPort_t *s, uint32_t baudRate);
bool isUartTransmitBufferEmpty(serialPort_t *s); bool isUartTransmitBufferEmpty(serialPort_t *s);

View file

@ -360,7 +360,7 @@ void gpsThread(void)
{ {
// read out available GPS bytes // read out available GPS bytes
if (gpsPort) { if (gpsPort) {
while (serialTotalBytesWaiting(gpsPort)) while (serialRxBytesWaiting(gpsPort))
gpsNewData(serialRead(gpsPort)); gpsNewData(serialRead(gpsPort));
} }
@ -1036,14 +1036,14 @@ void gpsEnablePassthrough(serialPort_t *gpsPassthroughPort)
#endif #endif
char c; char c;
while(1) { while(1) {
if (serialTotalBytesWaiting(gpsPort)) { if (serialRxBytesWaiting(gpsPort)) {
LED0_ON; LED0_ON;
c = serialRead(gpsPort); c = serialRead(gpsPort);
gpsNewData(c); gpsNewData(c);
serialWrite(gpsPassthroughPort, c); serialWrite(gpsPassthroughPort, c);
LED0_OFF; LED0_OFF;
} }
if (serialTotalBytesWaiting(gpsPassthroughPort)) { if (serialRxBytesWaiting(gpsPassthroughPort)) {
LED1_ON; LED1_ON;
serialWrite(gpsPort, serialRead(gpsPassthroughPort)); serialWrite(gpsPort, serialRead(gpsPassthroughPort));
LED1_OFF; LED1_OFF;

View file

@ -2141,7 +2141,7 @@ void cliProcess(void)
return; return;
} }
while (serialTotalBytesWaiting(cliPort)) { while (serialRxBytesWaiting(cliPort)) {
uint8_t c = serialRead(cliPort); uint8_t c = serialRead(cliPort);
if (c == '\t' || c == '?') { if (c == '\t' || c == '?') {
// do tab completion // do tab completion

View file

@ -1807,7 +1807,7 @@ void mspProcess(void)
setCurrentPort(candidatePort); setCurrentPort(candidatePort);
while (serialTotalBytesWaiting(mspSerialPort)) { while (serialRxBytesWaiting(mspSerialPort)) {
uint8_t c = serialRead(mspSerialPort); uint8_t c = serialRead(mspSerialPort);
bool consumed = mspProcessReceivedData(c); bool consumed = mspProcessReceivedData(c);

View file

@ -514,7 +514,7 @@ void init(void)
void processLoopback(void) { void processLoopback(void) {
if (loopbackPort) { if (loopbackPort) {
uint8_t bytesWaiting; uint8_t bytesWaiting;
while ((bytesWaiting = serialTotalBytesWaiting(loopbackPort))) { while ((bytesWaiting = serialRxBytesWaiting(loopbackPort))) {
uint8_t b = serialRead(loopbackPort); uint8_t b = serialRead(loopbackPort);
serialWrite(loopbackPort, b); serialWrite(loopbackPort, b);
}; };

View file

@ -374,7 +374,7 @@ static void processBinaryModeRequest(uint8_t address) {
static void flushHottRxBuffer(void) static void flushHottRxBuffer(void)
{ {
while (serialTotalBytesWaiting(hottPort) > 0) { while (serialRxBytesWaiting(hottPort) > 0) {
serialRead(hottPort); serialRead(hottPort);
} }
} }
@ -383,7 +383,7 @@ static void hottCheckSerialData(uint32_t currentMicros)
{ {
static bool lookingForRequest = true; static bool lookingForRequest = true;
uint8_t bytesWaiting = serialTotalBytesWaiting(hottPort); uint8_t bytesWaiting = serialRxBytesWaiting(hottPort);
if (bytesWaiting <= 1) { if (bytesWaiting <= 1) {
return; return;

View file

@ -160,7 +160,7 @@ static void smartPortDataReceive(uint16_t c)
static uint8_t lastChar; static uint8_t lastChar;
if (lastChar == FSSP_START_STOP) { if (lastChar == FSSP_START_STOP) {
smartPortState = SPSTATE_WORKING; smartPortState = SPSTATE_WORKING;
if (c == FSSP_SENSOR_ID1 && (serialTotalBytesWaiting(smartPortSerialPort) == 0)) { if (c == FSSP_SENSOR_ID1 && (serialRxBytesWaiting(smartPortSerialPort) == 0)) {
smartPortLastRequestTime = now; smartPortLastRequestTime = now;
smartPortHasRequest = 1; smartPortHasRequest = 1;
// we only responde to these IDs // we only responde to these IDs
@ -282,7 +282,7 @@ void handleSmartPortTelemetry(void)
return; return;
} }
while (serialTotalBytesWaiting(smartPortSerialPort) > 0) { while (serialRxBytesWaiting(smartPortSerialPort) > 0) {
uint8_t c = serialRead(smartPortSerialPort); uint8_t c = serialRead(smartPortSerialPort);
smartPortDataReceive(c); smartPortDataReceive(c);
} }

View file

@ -177,7 +177,12 @@ uint32_t millis(void) {
uint32_t micros(void) { return 0; } uint32_t micros(void) { return 0; }
uint8_t serialTotalBytesWaiting(serialPort_t *instance) { uint8_t serialRxBytesWaiting(serialPort_t *instance) {
UNUSED(instance);
return 0;
}
uint8_t serialTxBytesFree(serialPort_t *instance) {
UNUSED(instance); UNUSED(instance);
return 0; return 0;
} }