Hello,
I started to work my way through the leaflabs code related to USB. I have not looked at the original st.com code (which leaflabs wants to replace), because I do not want to overwhelm myself with too many comparisons.
I have some questions and observations about general USB questions and specific questions about how USB is implemented on LeafLabs products.
I have been using the beyondlogic.org/usbnutshell site to guide my reading and questions.
If my current understanding is not too far from the truth I will describe more observations and more questions in follow-up posts. So let's get started!
1) General statements:
There are four USB transfer/endpoint types: control, interrupt, bulk, and isochronous.
Full speed USB 2.0 devices (such as the Maple) use a packet size of 64 bytes for control transfers, a packet size of 64 bytes for interrupt transfers, a packet size up to 64 bytes for bulk transfers, and a packet size up to 1023 bytes for isochronous transfers.
For interrupt based transfers the device must wait until the host first polls the device before the device can send the contents of the buffer, even if the buffer is full and "ready" for transfer before the device is polled.
For isochronous transfers the timing between transfers is critical. Data transfer errors are not corrected.
For USB the host system splits time into 1 millisecond frames. Thus, there are 1000 frames per second.
2) Maple settings:
I realize the Maple code to support isochronous has not been implemented, but it would not use too many bytes in descriptors.h
to define it in case a user wanted to develop the code (while minimizing the number of files edited):
#define EP_TYPE_ISOCHRONOUS 0x01
3) USB timeout:
If a USB interrupt transfer buffer is not full, the device will wait (even if it is polled by the system) until more data is added to the buffer before the data is sent. However, if the timeout time elapses, the device will send the interrupt transfer data even if the buffer is not full.
Is there a reason for setting the timeout to 50 milliseconds? Would a shorter timeout be better?
With a 50 millisecond timeout, in each second there would be at most 20 timeouts (20 X 50 ms = 1000 ms). So if user code is very inefficient and if only one character is placed in the transmit buffer before the timeout elapses then the data transfer rate would be only 160 bits per second.
However, if the timeout were reduced to 10 milliseconds, the same inefficient code would transfer at a rate of 800 bits per second, still slow, but still five times faster than 160 bits per second.
I appreciate that the timeout size cannot be smaller than 1 millisecond, because USB uses 1 millisecond length frames.
4) USB polling frequency, USB frames, and maximum interrupt transfer rates:
How is the polling time set for USB "interrupt" transfers? I read somewhere that 5 millisecond polling is used, but I cannot find the reference.
Is only one packet of data sent each time the host polls a USB device for an interrupt type transfer?
If the polling time is set to the minimum 1 millisecond (since USB uses 1 millisecond frames) and only one packet is sent per frame, then is the maximum rate for interrupt transfers 64,000 bytes per second?
This calculated transfer rate seems very low, which suggests I am missing something or making a wrong assumption somewhere.
5) Full interrupt transfer buffers:
If a Maple based program uses a 64 byte buffer for interrupt type transfer how does the program know when the buffer has been sent?
In other words, if an interrupt transfer type buffer is full how does the program know to "wait" before it tries to add more data to the buffer (assuming data loss is not desirable).
I believe this is the blocking / nonblocking problem described by gbulmer in:
http://forums.leaflabs.com/topic.php?id=659#post-3711
6) USB bandwidth management: data transfer and isochronous buffer size:
I believe it is possible to have multiple isochronous devices connected to a host (eg. two USB music sources connected to a mixer). Assuming there is enough bandwidth (which is managed by the host) to accommodate all the isochronous devices how does each device learn to "play fairly" so a device does not hog all the bandwidth? Is it up the the programmer(s) or does the host system help make this decision?
I appreciate that 10% of the bandwidth is for control transfers.
If full speed USB is 12 megabits per second, then 1.2 megabytes per second is used for control transfers, leaving 10.8 megabits per second for data (interrupt, isochronous, and bulk types).
10.8 megabits per second = 1.35 megabytes per second.
There are 1000 frames per second, so during each frame 1.35 kilobytes (1035 bytes) of data can be transferred.
This number is consistent with the 1023 maximum byte size for isochronous transfers.
If my math and assumptions are correct then the sum of the packet sizes (for all transfer types) needs to be 1035 bytes or less.
There are several implications of this calculation.
For isochronous transfer, is it best to keep the packet size as small as possible?
For example, assume Maple sketch wants to transfer 100,000 bytes per second using isochronous transfers. Is it best to send only 100 bytes per frame (sending data in every frame). How about sending 200 bytes per frame (and sending data during only half the frames)?
Does this mean it is not possible for two isochronous devices (deviceA and deviceB) whose buffers are each 1023 bytes to coexist peacefully on the same USB wire (if no data loss is desired)?
In the above example, will the system just take 1023 bytes of data from deviceA every other frame and from deviceB every other frame (dropping half the data, but maintaining the proper data rate)? Or is it up to the programmers of each device to not hog the bandwidth? How easy is it to figure out the buffer size used of an isochronous device?
7) Thanks. That is it for now.
Stephen from NYC
Edited: A simple enumeration error was fixed. However, a conversion "1.35 kilobytes (1035 bytes)" in section 6 was left unchanged. This is commented on in a response below.