serial: allow buffering to speed up USB virtual COM ports.

Add begin write and end write hints.  If implemented by the serial
driver, then the driver can buffer up data sent via serialWrite() and
flush it when serialEndWrite() is called.

Implemented at the buffer level as it requires the least change to how
serial_msp and serial_cli are architected.

Also tidy up the visibility in the VCP driver.

Signed-off-by: Michael Hope <mlhx@google.com>
This commit is contained in:
Michael Hope 2015-07-19 15:56:37 +02:00 committed by borisbstyle
parent 0e460c18b0
commit 195456f9ac
7 changed files with 84 additions and 2498 deletions

View File

@ -85,3 +85,15 @@ void serialWriteBufShim(void *instance, void *data, int count)
{
serialWriteBuf((serialPort_t *)instance, data, count);
}
void serialBeginWrite(serialPort_t *instance)
{
if (instance->vTable->beginWrite)
instance->vTable->beginWrite(instance);
}
void serialEndWrite(serialPort_t *instance)
{
if (instance->vTable->endWrite)
instance->vTable->endWrite(instance);
}

View File

@ -75,6 +75,9 @@ struct serialPortVTable {
void (*setMode)(serialPort_t *instance, portMode_t mode);
void (*writeBuf)(serialPort_t *instance, void *data, int count);
// Optional functions used to buffer large writes.
void (*beginWrite)(serialPort_t *instance);
void (*endWrite)(serialPort_t *instance);
};
void serialWrite(serialPort_t *instance, uint8_t ch);
@ -90,3 +93,5 @@ uint32_t serialGetBaudRate(serialPort_t *instance);
// A shim that adapts the bufWriter API to the serialWriteBuf() API.
void serialWriteBufShim(void *instance, void *data, int count);
void serialBeginWrite(serialPort_t *instance);
void serialEndWrite(serialPort_t *instance);

View File

@ -323,5 +323,7 @@ const struct serialPortVTable uartVTable[] = {
isUartTransmitBufferEmpty,
uartSetMode,
.writeBuf = NULL,
.beginWrite = NULL,
.endWrite = NULL,
}
};

View File

@ -23,6 +23,7 @@
#include "platform.h"
#include "build_config.h"
#include "common/utils.h"
#include "usb_core.h"
#include "usb_init.h"
@ -103,9 +104,42 @@ static void usbVcpWriteBuf(serialPort_t *instance, void *data, int count)
}
}
static bool usbVcpFlush(vcpPort_t *port)
{
uint8_t count = port->txAt;
port->txAt = 0;
if (count == 0) {
return true;
}
if (!usbIsConnected() || !usbIsConfigured()) {
return false;
}
uint32_t txed;
uint32_t start = millis();
do {
txed = CDC_Send_DATA(port->txBuf, count);
} while (txed != count && (millis() - start < USB_TIMEOUT));
return txed == count;
}
static void usbVcpWrite(serialPort_t *instance, uint8_t c)
{
usbVcpWriteBuf(instance, &c, sizeof(c));
vcpPort_t *port = container_of(instance, vcpPort_t, port);
port->txBuf[port->txAt++] = c;
if (!port->buffering || port->txAt >= ARRAYLEN(port->txBuf)) {
usbVcpFlush(port);
}
}
static void usbVcpBeginWrite(serialPort_t *instance)
{
vcpPort_t *port = container_of(instance, vcpPort_t, port);
port->buffering = true;
}
uint8_t usbTxBytesFree() {
@ -113,7 +147,27 @@ uint8_t usbTxBytesFree() {
return 255;
}
const struct serialPortVTable usbVTable[] = { { usbVcpWrite, usbVcpAvailable, usbTxBytesFree, usbVcpRead, usbVcpSetBaudRate, isUsbVcpTransmitBufferEmpty, usbVcpSetMode, .writeBuf = usbVcpWriteBuf } };
static void usbVcpEndWrite(serialPort_t *instance)
{
vcpPort_t *port = container_of(instance, vcpPort_t, port);
port->buffering = false;
usbVcpFlush(port);
}
static const struct serialPortVTable usbVTable[] = {
{
.serialWrite = usbVcpWrite,
.serialTotalRxWaiting = usbVcpAvailable,
.serialTotalTxFree = usbTxBytesFree,
.serialRead = usbVcpRead,
.serialSetBaudRate = usbVcpSetBaudRate,
.isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty,
.setMode = usbVcpSetMode,
.beginWrite = usbVcpBeginWrite,
.endWrite = usbVcpEndWrite,
.writeBuf = usbVcpWriteBuf
}
};
serialPort_t *usbVcpOpen(void)
{

View File

@ -21,6 +21,12 @@
typedef struct {
serialPort_t port;
// Buffer used during bulk writes.
uint8_t txBuf[20];
uint8_t txAt;
// Set if the port is in bulk write mode and can buffer.
bool buffering;
} vcpPort_t;
serialPort_t *usbVcpOpen(void);

File diff suppressed because it is too large Load Diff

View File

@ -455,6 +455,8 @@ static uint32_t read32(void)
static void headSerialResponse(uint8_t err, uint8_t responseBodySize)
{
serialBeginWrite(mspSerialPort);
serialize8('$');
serialize8('M');
serialize8(err ? '!' : '>');
@ -476,6 +478,7 @@ static void headSerialError(uint8_t responseBodySize)
static void tailSerialReply(void)
{
serialize8(currentPort->checksum);
serialEndWrite(mspSerialPort);
}
static void s_struct(uint8_t *cb, uint8_t siz)