Skip to content

Commit

Permalink
Add uartWriteBuf() to improve performance
Browse files Browse the repository at this point in the history
Optimised transmit buffer space check
Tidy up group duration calculations
Add uartBeginWrite, uartEndWrite and serialWriteBufNoFlush
  • Loading branch information
SteveCEvans committed Feb 25, 2024
1 parent ef75335 commit b5f92a6
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 37 deletions.
26 changes: 16 additions & 10 deletions src/main/drivers/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ void serialWrite(serialPort_t *instance, uint8_t ch)
}


void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count)
void serialWriteBufNoFlush(serialPort_t *instance, const uint8_t *data, int count)
{
if (instance->vTable->writeBuf) {
instance->vTable->writeBuf(instance, data, count);
} else {
for (const uint8_t *p = data; count > 0; count--, p++) {

while (!serialTxBytesFree(instance)) {
};
// The transmit buffer is large enough to hold any single message, so only wait once
while (serialTxBytesFree(instance) < (uint32_t)count) {
};

for (const uint8_t *p = data; count > 0; count--, p++) {
serialWrite(instance, *p);
}
}
Expand Down Expand Up @@ -107,11 +107,6 @@ void serialSetBaudRateCb(serialPort_t *serialPort, void (*cb)(serialPort_t *cont
}
}

void serialWriteBufShim(void *instance, const uint8_t *data, int count)
{
serialWriteBuf((serialPort_t *)instance, data, count);
}

void serialBeginWrite(serialPort_t *instance)
{
if (instance->vTable->beginWrite)
Expand All @@ -123,3 +118,14 @@ void serialEndWrite(serialPort_t *instance)
if (instance->vTable->endWrite)
instance->vTable->endWrite(instance);
}

void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count)
{
serialBeginWrite(instance);
serialWriteBufNoFlush(instance, data, count);
serialEndWrite(instance);
}
void serialWriteBufShim(void *instance, const uint8_t *data, int count)
{
serialWriteBuf((serialPort_t *)instance, data, count);
}
1 change: 1 addition & 0 deletions src/main/drivers/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ void serialWrite(serialPort_t *instance, uint8_t ch);
uint32_t serialRxBytesWaiting(const serialPort_t *instance);
uint32_t serialTxBytesFree(const serialPort_t *instance);
void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count);
void serialWriteBufNoFlush(serialPort_t *instance, const uint8_t *data, int count);
uint8_t serialRead(serialPort_t *instance);
void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate);
void serialSetMode(serialPort_t *instance, portMode_e mode);
Expand Down
67 changes: 64 additions & 3 deletions src/main/drivers/serial_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,67 @@ static void uartWrite(serialPort_t *instance, uint8_t ch)
}
}

static void uartBeginWrite(serialPort_t *instance)
{
uartPort_t *uartPort = (uartPort_t *)instance;

// Check if the TX line is being pulled low by an unpowered peripheral
if (uartPort->checkUsartTxOutput && !uartPort->checkUsartTxOutput(uartPort)) {
// TX line is being pulled low, so don't transmit
return;
}
}

static void uartWriteBuf(serialPort_t *instance, const void *data, int count)
{
uartPort_t *uartPort = (uartPort_t *)instance;
uartDevice_t *uart = container_of(uartPort, uartDevice_t, port);
const uint8_t *bytePtr = (const uint8_t*)data;

// Check if the TX line is being pulled low by an unpowered peripheral
if (uartPort->checkUsartTxOutput && (uart->txPinState != TX_PIN_ACTIVE)) {
// TX line is being pulled low, so don't transmit
return;
}

for (int i = 0; i < count; i++) {
uartPort->port.txBuffer[uartPort->port.txBufferHead] = *bytePtr++;

if (uartPort->port.txBufferHead + 1 >= uartPort->port.txBufferSize) {
uartPort->port.txBufferHead = 0;
} else {
uartPort->port.txBufferHead++;
}
}
}

static void uartEndWrite(serialPort_t *instance)
{
uartPort_t *uartPort = (uartPort_t *)instance;
uartDevice_t *uart = container_of(uartPort, uartDevice_t, port);

// Check if the TX line is being pulled low by an unpowered peripheral
if (uartPort->checkUsartTxOutput && (uart->txPinState != TX_PIN_ACTIVE)) {
// TX line is being pulled low, so don't transmit
return;
}

#ifdef USE_DMA
if (uartPort->txDMAResource) {
uartTryStartTxDMA(uartPort);
} else
#endif
{
#if defined(USE_HAL_DRIVER)
__HAL_UART_ENABLE_IT(&uartPort->Handle, UART_IT_TXE);
#elif defined(USE_ATBSP_DRIVER)
usart_interrupt_enable(uartPort->USARTx, USART_TDBE_INT, TRUE);
#else
USART_ITConfig(uartPort->USARTx, USART_IT_TXE, ENABLE);
#endif
}
}

const struct serialPortVTable uartVTable[] = {
{
.serialWrite = uartWrite,
Expand All @@ -308,9 +369,9 @@ const struct serialPortVTable uartVTable[] = {
.setMode = uartSetMode,
.setCtrlLineStateCb = NULL,
.setBaudRateCb = NULL,
.writeBuf = NULL,
.beginWrite = NULL,
.endWrite = NULL,
.writeBuf = uartWriteBuf,
.beginWrite = uartBeginWrite,
.endWrite = uartEndWrite,
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/main/msp/msp_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ static int mspSerialSendFrame(mspPort_t *msp, const uint8_t * hdr, int hdrLen, c
// Transmit frame
serialBeginWrite(msp->port);
serialWriteBuf(msp->port, hdr, hdrLen);
serialWriteBuf(msp->port, data, dataLen);
serialWriteBufNoFlush(msp->port, data, dataLen);
serialWriteBuf(msp->port, crc, crcLen);
serialEndWrite(msp->port);

Expand Down
25 changes: 13 additions & 12 deletions src/main/osd/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,7 @@ bool osdUpdateCheck(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs)
void osdUpdate(timeUs_t currentTimeUs)
{
static uint16_t osdStateDurationFractionUs[OSD_STATE_COUNT] = { 0 };
static uint32_t osdElementDurationUs[OSD_ITEM_COUNT] = { 0 };
static uint32_t osdElementDurationFractionUs[OSD_ITEM_COUNT] = { 0 };
static uint8_t osdElementGroupMemberships[OSD_ITEM_COUNT];
static uint16_t osdElementGroupTargetFractionUs[OSD_GROUP_COUNT] = { 0 };
static uint16_t osdElementGroupDurationFractionUs[OSD_GROUP_COUNT] = { 0 };
Expand Down Expand Up @@ -1519,9 +1519,6 @@ void osdUpdate(timeUs_t currentTimeUs)

// Reset groupings
for (elementGroup = 0; elementGroup < OSD_GROUP_COUNT; elementGroup++) {
if (osdElementGroupDurationFractionUs[elementGroup] > (OSD_ELEMENT_RENDER_TARGET << OSD_EXEC_TIME_SHIFT)) {
osdElementGroupDurationFractionUs[elementGroup] = 0;
}
osdElementGroupTargetFractionUs[elementGroup] = 0;
}

Expand All @@ -1530,13 +1527,15 @@ void osdUpdate(timeUs_t currentTimeUs)
// Based on the current element rendering, group to execute in approx 40us
for (uint8_t curElement = 0; curElement < activeElements; curElement++) {
if ((osdElementGroupTargetFractionUs[elementGroup] == 0) ||
(osdElementGroupTargetFractionUs[elementGroup] + (osdElementDurationUs[curElement]) <= (OSD_ELEMENT_RENDER_TARGET << OSD_EXEC_TIME_SHIFT)) ||
((osdElementGroupTargetFractionUs[elementGroup] + osdElementDurationFractionUs[curElement]) <= (OSD_ELEMENT_RENDER_TARGET << OSD_EXEC_TIME_SHIFT)) ||
(elementGroup == (OSD_GROUP_COUNT - 1))) {
osdElementGroupTargetFractionUs[elementGroup] += osdElementDurationUs[curElement];
// If group membership changes, reset the stats for the group
// Add the time taken to render this element to the current group
osdElementGroupTargetFractionUs[elementGroup] += osdElementDurationFractionUs[curElement];
// If group membership changes, reset the estimated duration for the group
if (osdElementGroupMemberships[curElement] != elementGroup) {
osdElementGroupDurationFractionUs[elementGroup] = osdElementGroupTargetFractionUs[elementGroup] + (OSD_ELEMENT_RENDER_GROUP_MARGIN << OSD_EXEC_TIME_SHIFT);
}
// Add the element to this group
osdElementGroupMemberships[curElement] = elementGroup;
} else {
elementGroup++;
Expand All @@ -1562,7 +1561,6 @@ void osdUpdate(timeUs_t currentTimeUs)
bool moreElements = true;

do {
timeUs_t startElementTime = micros();
uint8_t osdCurrentElement = osdGetActiveElement();

// This element should be rendered in the next group
Expand All @@ -1571,22 +1569,25 @@ void osdUpdate(timeUs_t currentTimeUs)
break;
}

timeUs_t startElementTime = micros();

moreElements = osdDrawNextActiveElement(osdDisplayPort, currentTimeUs);

executeTimeUs = micros() - startElementTime;

if (executeTimeUs > (osdElementDurationUs[osdCurrentElement] >> OSD_EXEC_TIME_SHIFT)) {
osdElementDurationUs[osdCurrentElement] = executeTimeUs << OSD_EXEC_TIME_SHIFT;
} else if (osdElementDurationUs[osdCurrentElement] > 0) {
if (executeTimeUs > (osdElementDurationFractionUs[osdCurrentElement] >> OSD_EXEC_TIME_SHIFT)) {
osdElementDurationFractionUs[osdCurrentElement] = executeTimeUs << OSD_EXEC_TIME_SHIFT;
} else if (osdElementDurationFractionUs[osdCurrentElement] > 0) {
// Slowly decay the max time
osdElementDurationUs[osdCurrentElement]--;
osdElementDurationFractionUs[osdCurrentElement]--;
}
} while (moreElements);

if (moreElements) {
// There are more elements to draw
break;
}

#ifdef USE_SPEC_PREARM_SCREEN
osdDrawSpec(osdDisplayPort);
#endif // USE_SPEC_PREARM_SCREEN
Expand Down
4 changes: 2 additions & 2 deletions src/main/target/common_pre.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
// Dependency for CMS is defined outside this block.
#define USE_OSD_QUICK_MENU
#define USE_RC_STATS
#define USE_SPEC_PREARM_SCREEN
//#define USE_SPEC_PREARM_SCREEN
#endif

#define USE_BATTERY_CONTINUE
Expand Down Expand Up @@ -447,7 +447,7 @@
#define USE_RC_STATS
#endif
#ifndef USE_SPEC_PREARM_SCREEN
#define USE_SPEC_PREARM_SCREEN
//#define USE_SPEC_PREARM_SCREEN
#endif
#endif

Expand Down
18 changes: 9 additions & 9 deletions src/main/telemetry/srxl.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,15 +625,15 @@ static void convertVtxTmData(spektrumVtx_t * vtx)
/*
typedef struct
{
UINT8 identifier;
UINT8 sID; // Secondary ID
UINT8 band; // VTX Band (0 = Fatshark, 1 = Raceband, 2 = E, 3 = B, 4 = A, 5-7 = Reserved)
UINT8 channel; // VTX Channel (0-7)
UINT8 pit; // Pit/Race mode (0 = Race, 1 = Pit). Race = (normal operating) mode. Pit = (reduced power) mode. When PIT is set, it overrides all other power settings
UINT8 power; // VTX Power (0 = Off, 1 = 1mw to 14mW, 2 = 15mW to 25mW, 3 = 26mW to 99mW, 4 = 100mW to 299mW, 5 = 300mW to 600mW, 6 = 601mW+, 7 = manual control)
UINT16 powerDec; // VTX Power as a decimal 1mw/unit
UINT8 region; // Region (0 = USA, 1 = EU, 0xFF = N/A)
UINT8 rfu[7]; // reserved
UINT8 identifier;
UINT8 sID; // Secondary ID
UINT8 band; // VTX Band (0 = Fatshark, 1 = Raceband, 2 = E, 3 = B, 4 = A, 5-7 = Reserved)
UINT8 channel; // VTX Channel (0-7)
UINT8 pit; // Pit/Race mode (0 = Race, 1 = Pit). Race = (normal operating) mode. Pit = (reduced power) mode. When PIT is set, it overrides all other power settings
UINT8 power; // VTX Power (0 = Off, 1 = 1mw to 14mW, 2 = 15mW to 25mW, 3 = 26mW to 99mW, 4 = 100mW to 299mW, 5 = 300mW to 600mW, 6 = 601mW+, 7 = manual control)
UINT16 powerDec; // VTX Power as a decimal 1mw/unit
UINT8 region; // Region (0 = USA, 1 = EU, 0xFF = N/A)
UINT8 rfu[7]; // reserved
} STRU_TELE_VTX;
*/

Expand Down

0 comments on commit b5f92a6

Please sign in to comment.