USB FS Maximum Throughput
Posted: Thu Oct 29, 2015 6:30 pm
I have been using 4bit SDIO on a STM32F411RE board and have been achieving ~1.2MB/s using FatFS to save over 100MB of sensor data on a SD card. Now I'm looking for ways of getting that data onto a computer without removing the SD card from the board.
I first tried implementing Mass Storage, but was unable to get it working reliably on both OSX and Windows and it was unclear whether that was going to be performant using FS anyways. Next I figured I could just transfer the data using the serial driver, and after increasing the USB serial buffers, I have only been able to achieve ~150KB/s, which is just not fast enough for my purposes. Is this the best I can hope to achieve with FS? I read some older threads and it sounded like I could bypass the queues of the serial driver and use usbPrepareTransmit() and usbStartTransmitI() directly but I am still struggling to get that to work as well. Can anybody comment on the kind of performance improvement I might see by using that technique? I also read that implementing double-buffering in the USB driver might be the only way to improve throughput, but it's unclear if this is something that is still on the horizon for ChibiOS 3. Finally, I've seen the recent discussion about using isochronous USB mode, and while I realize it's not really for bulk data transfer, perhaps there's a way to leverage that functionality somehow?
I guess my questions boil down to this: If I'm looking to achieve > 150KB/s USB transfer, where should I be focusing my efforts? If somebody could confirm they've achieved greater speeds using MSC w/ USB FS (or any method for that matter), I'd consider spending more time getting that method to work. If it's unlikely that I'll ever see anything better than 150KB/s short of implementing double-buffering then I'll just have to deal with the slow speeds (but at least I can move on).
BTW, here is the code I'm using to measure speed.
I first tried implementing Mass Storage, but was unable to get it working reliably on both OSX and Windows and it was unclear whether that was going to be performant using FS anyways. Next I figured I could just transfer the data using the serial driver, and after increasing the USB serial buffers, I have only been able to achieve ~150KB/s, which is just not fast enough for my purposes. Is this the best I can hope to achieve with FS? I read some older threads and it sounded like I could bypass the queues of the serial driver and use usbPrepareTransmit() and usbStartTransmitI() directly but I am still struggling to get that to work as well. Can anybody comment on the kind of performance improvement I might see by using that technique? I also read that implementing double-buffering in the USB driver might be the only way to improve throughput, but it's unclear if this is something that is still on the horizon for ChibiOS 3. Finally, I've seen the recent discussion about using isochronous USB mode, and while I realize it's not really for bulk data transfer, perhaps there's a way to leverage that functionality somehow?
I guess my questions boil down to this: If I'm looking to achieve > 150KB/s USB transfer, where should I be focusing my efforts? If somebody could confirm they've achieved greater speeds using MSC w/ USB FS (or any method for that matter), I'd consider spending more time getting that method to work. If it's unlikely that I'll ever see anything better than 150KB/s short of implementing double-buffering then I'll just have to deal with the slow speeds (but at least I can move on).
BTW, here is the code I'm using to measure speed.
Code: Select all
uint16_t i;
static uint8_t data[SERIAL_USB_BUFFERS_SIZE] = { 0 };
static time_measurement_t time;
float speed;
chTMObjectInit(&time);
chTMStartMeasurementX(&time);
//Send 1MB of data, in chunks equal to the usb buffer size
for (i=0; i < (1024*1024 / SERIAL_USB_BUFFERS_SIZE); i++)
{
chSequentialStreamWrite((BaseSequentialStream*)&SDU1, data, SERIAL_USB_BUFFERS_SIZE);
}
chTMStopMeasurementX(&time);
speed = 1024000 * ((float)1 / RTC2MS(STM32_SYSCLK, time.cumulative));
cliPrintf("USB Transfer Speed: %0.2f KB/s\r\n", speed);