It is not uncommon to get asked about data throughput in communication protocols. As engineers, most of us are thought two or three wired communications protocols in school, usually, these have not overhead (like a UART or SPI), or very little (like IIC), they are, in practical terms, “What You See is What You Get” protocols. Once we get to work with the “adult” protocols, things aren’t as simple. A bunch of overhead has been added to complicate the protocol (with the purpose of making it simpler to use to the end user). USB is one of those, the simple-to-use label it is marketed as, plug and play, user friendly, etc., will, of course, make it more complicated to us “development folk”.
The low end embedded world (a.k.a. the cheap-but-functional-MCU-world if you didn’t get the low end part), is far more confused with protocols like these, for the silicon designers, it is a task of near magic to get slow MCUs with limited resources to cram high speed, high resource usage peripherals in those tiny 8 bit dies. Same goes for us programmers that are used to sending data from one end of the board to the other, and are used to sending data out “to the real world” only through a DB9 connector.
So you have spent a couple of otherwise enjoyable nights learning all the secrets behind the USB 2.0 specification, plus any other helpful document you could find at www.usb.org and the application notes at www.freescale.com/usb you have in your hands the USB 8 bit “magical” MCU. You fire up your compiler, open up the reference code from the app notes and you start figuring out how to send commands, data, status and more data to the computer and back. You grab the very first USB endpoint you can find (let’s call it: “Endpoint 1”) and start building this very interesting protocol similar to the one you used in your first serial communications project in college. You will have a couple of bytes to address different stuff, a couple of bytes to tell the stuff what you are doing, maybe two extra byte to really narrow down the previous command to a very specific task, some data and some sort of data integrity check (like a CRC) at the very end for you to make sure all the data you sent, is correct. Taking away the data, you have just added 8 bytes that aren’t really part of the data (the important thing you are planning to move from computer to MCU), every data transfer these 8 bytes will clunk up your already filled with overhead communications.
Stop! Think about the USB specification for a while and then go to your MCU data sheet, find out how many endpoints it has (6 in the Freescale new MC9S08JM60). Think about how many different commands you want to send and how many different functions you want to do with this data. Split it into the most important parts and think about how frequently each data block is needed. Maybe you do need commands, but only every 4 milliseconds and with about 6 bytes, you could use an endpoint (a USB pipe) just for that, saving you the trouble of adding some more bytes to tell your application if the data is commands or else. Put that data in an interrupt endpoint and have the computer send interrupt packets every 4 milliseconds (this is defined in the configuration descriptor of the USB module). Maybe you need to send big chunks of 64 bytes and be very sure each one of those bytes is received exactly as it was sent. Declare a bulk endpoint and send the 64 byte packages through it, bulk endpoints are designed to guarantee data transmission, so you will save up that extra redundancy check overhead on the communications and on the processor. If you just want to send a lot of data very fast, configure another endpoint as isochronous, this one will be optimized to send data faster.
Put it all together and you have optimized your USB application taking advantage of all this previously not fully understood overhead, your code will also be cleaner and it will allow the rest of the application more CPU load, so remember, use the pipes.
For more information on Freescale USB MCU’s go to:
Low end, low cost 8-bit USB MCU, the new S08JS.
Same as before but with more memory/resources, S08JM family.
The 32-bit version, with integrated OTG, host and device controller, MCF51JM.
To better understand the new USB solutions visits the above links and click on the “Application notes” link.