user1426923
user1426923

Reputation: 77

How do I increase the speed of my USB cdc device?

I am upgrading the processor in an embedded system for work. This is all in C, with no OS. Part of that upgrade includes migrating the processor-PC communications interface from IEEE-488 to USB. I finally got the USB firmware written, and have been testing it. It was going great until I tried to push through lots of data only to discover my USB connection is slower than the old IEEE-488 connection. I have the USB device enumerating as a CDC device with a baud rate of 115200 bps, but it is clear that I am not even reaching that throughput, and I thought that number was a dummy value that is a holdover from RS232 days, but I might be wrong. I control every aspect of this from the front end on the PC to the firmware on the embedded system.

I am assuming my issue is how I write to the USB on the embedded system side. Right now my USB_Write function is run in free time, and is just a while loop that writes one char to the USB port until the write buffer is empty. Is there a more efficient way to do this?

One of my concerns that I have, is that in the old system we had a board in the system dedicated to communications. The CPU would just write data across a bus to this board, and it would handle communications, which means that the CPU didn't have to waste free time handling the actual communications, but could offload the communications to a "co processor" (not a CPU but functionally the same here). Even with this concern though I figured I should be getting faster speeds given that full speed USB is on the order of MB/s while IEEE-488 is on the order of kB/s.

In short is this more likely a fundamental system constraint or a software optimization issue?

Upvotes: 5

Views: 6179

Answers (1)

Michael Shaw
Michael Shaw

Reputation: 304

I thought that number was a dummy value that is a holdover from RS232 days, but I might be wrong.

You are correct, the baud number is a dummy value. If you create a CDC/RS232 adapter you would use this to configure your RS232 hardware, in this case it means nothing.

Is there a more efficient way to do this?

Absolutely! You should be writing chunks of data the same size as your USB endpoint for maximum transfer speed. Depending on the device you are using your stream of single byte writes may be gathered into a single packet before sending but from my experience (and your results) this is unlikely.

Depending on your latency requirements you can stick in a circular buffer and only issue data from it to the USB_Write function when you have ENDPOINT_SZ number of byes. If this results in excessive latency or your interface is not always communicating you may want to implement Nagles algorithm.

One of my concerns that I have, is that in the old system we had a board in the system dedicated to communications.

The NXP part you mentioned in the comments is without a doubt fast enough to saturate a USB full speed connection.

In short is this more likely a fundamental system constraint or a software optimization issue?

I would consider this a software design issue rather than an optimisation one, but no, it is unlikely you are fundamentally stuck.

Do take care to figure out exactly what sort of USB connection you are using though, if you are using USB 1.1 you will be limited to 64KB/s, USB 2.0 full speed you will be limited to 512KB/s. If you require higher throughput you should migrate to using a separate bulk endpoint for the data transfer.

I would recommend reading through the USB made simple site to get a good overview of the various USB speeds and their capabilities.

One final issue, vendor CDC libraries are not always the best and implementations of the CDC standard can vary. You can theoretically get more data through a CDC endpoint by using larger endpoints, I have seen this bring host side drivers to their knees though - if you go this route create a custom driver using bulk endpoints.

Try testing your device on multiple systems, you may find you get quite different results between windows and linux. This will help to point the finger at the host end.

And finally, make sure you are doing big buffered reads on the host side, USB will stop transferring data once the host side buffers are full.

Upvotes: 3

Related Questions