Because the transfer rates of SerialUSB.readBytes are slow (I transfer pixel data for a 240x400 px touchscreen from my PC and get less than one full frame per second), I decided to write my own read function which has almost eight times faster transfer rates (with an average of around 1270 KB/s compared to readBytes with around 160 KB/s). If I actually transfer the data to the screen, I end up with around 620 KB/s which is enough for more than 2 frames per second. [EDIT : I am talking about 192 KB per transfer]
The difference is mostly caused by the amount of function calls. SerialUSB.accept calls USDB_Recv for each byte.
A disadvantage of it is that it sometimes seems to skip or corrupt bytes but I couldn't find out why. Adding acknowledge data which the PC waits for seems to make it less likely.
Here's the code :
void WaitReadUSB(void *data, uint32_t len)
{
uint32_t i = 0;
if (len > 0)
{
while (!USBD_Available(CDC_RX)){}
while (i < len)
{
i += USBD_Recv2(CDC_RX, &((byte*)data)[i], min(len-i,16));
if (!USBD_Available(CDC_RX))
{
udd_ack_fifocon(CDC_RX);
if (i < len)
{
while (!USBD_Available(CDC_RX))
{}
}
}
}
}
}
USBD_Recv2 is a modified USBD_Recv that only calls UDD_Recv one. I inserted it into USBCore.cpp from the Arduino Due package (and the declaration into USBAPI.h).
uint32_t USBD_Recv2(uint32_t ep, void* d, uint32_t len)
{
if (!_usbConfiguration)
return -1;
LockEP lock(ep);
len = min(UDD_FifoByteCount(ep & 0xF),len);
uint8_t* dst = (uint8_t*)d;
UDD_Recv(ep & 0xF, dst, len);
if (len && !UDD_FifoByteCount(ep & 0xF)) // release empty buffer
UDD_ReleaseRX(ep & 0xF);
return len;
}
Even if the data isn't used, SerialUSB.accept still is called by an interrupt handler in USBCore.cpp which results in loss of data until the buffer is filled. I just added an additional parameter to Serial_::begin that specifies whether Serial_::accept should just return immediately (it is in CDC.cpp and the header is USBAPI.h).