What is the maximum speed of the STM32 USB CDC? - usb

I'm using an STM32L151 to communicate with a PC using USB CDC. I used the STM32 HAL libraries to create my project.
I found that the USB sends data in 1 ms intervals, and each time 64 bytes are being sent. So, is the maximum speed of the USB CDC 64 kbyte/s? That is much lower than the USB Full Speed data rate of 12 Mbit/s. How can I reach this speed, or at least a fraction of this speed?

Nope. If your code is "fast enough", the maximum CDC speed is about 1MByte/sec. This may require a big (>1KB) FIFO on the device side. Oh, and the PC side must be able to read the data fast enough, e.g. with big buffers.
The 64KByte/s limit applies for USB HID which uses interrupt endpoints. USB CDC interface uses faster bulk endpoints.

USB FS frame is 1ms so if you put 64 bytes to the buffer (using the HAL function) - it will send those 64 bytes in the next frame. And it will not send any more data until another 1ms frame
How to increase this speed -> aggregate your data in larger chunks and send more data in the one transaction (up to 8kB using HAL libraries).

Related

How is it possible to send HID packets longer than 64 bytes?

While researching the HID specification for a current project, I stumbled across the following phrase:
Using USB terminology, a device may send or receive a transaction every USB frame (1 millisecond). A transaction may be made up of multiple packets (token, data, handshake) but is limited in size to 8 bytes for low-speed devices and 64 bytes for high-speed devices.
This leads me to believe that the maximum size for a HID packet is 64 bytes.
However, examining the report descriptors for some other devices I see that packets of more than 500 bytes are being used. How is this possible? Are these devices violating the USB spec? If so, what might that imply in terms of compatibility across different platforms?
As far as I know, the last HID specification is much older than the recent USB specs; IIRC the latest version is 1.11 which dates back to 2001.
There is low-speed, full-speed, and high-speed USB these days, and I think the HID spec was never changed to reflect this.
The maximum packet size for high-speed is 64 bytes for control transfers, 1024 bytes for interrupt transfers and isochronous transfers, and 512 bytes for bulk transfers.
See USB in a NutShell, which I think is more up-to-date. There are other sources, of course.
I am not entirely sure if all this applies to HID devices as well these days, what with the HID spec not having changed, but I assume high-speed HID devices exist now that use larger packets as described in the newer USB specs.

USB performance issues

I am trying to transfer data over USB. These are packets of at most 64 bytes which get sent at a frequency of 4KHz. This gives a bit rate of about 2Mb/s.
The software task that picks up this data runs at 2.5 KHz.
Ideally we never want packets to get there slower than 2.5 KHz (so 2 KHz isn't very good).
Is anyone aware of any generic limits on what USB can achieve?
We are running on a main board which has a 1.33 GHz running QNX and a daughter board which is a TWR K60F120M tower system running MQX.
Apart from the details of the system, is USB supposed to be used in this kind of data transfers, i.e., high frequency and short packet sizes?
Many Thanks for your help
MG
USB, even at its slowest spec (1.1), can transfer data at up to 12MB/sec, provided you use the proper transfer mode. USB will process 1000 "frames" per second. The frames contain control and data information, and various portions of each frame are used for various purposes, and thus the total information content is "multiplexed" amongst these competing requirements.
Low speed devices will use just a few bytes in a frame to send or receive their data. Examples are modems, mice, keyboards, etc. The so-called Full Speed devices (in USB 1.1) can achieve up to 12 MB/sec by using isochronous mode transfers, meaning they get carved out a nice big chunk of each frame, and can send that much data (a fixed size) each time a frame comes along. This is the mode audio devices use to stream the relatively data-intensive music to USB speakers, for example.
If you are able to do a little bit of local buffering, you may be able to use isochronous mode to get your 64 bytes of data sent at 1 KHz, but with 2 or 3 periods (at 2.5KHz) worth of data in the USB frame transfer. You'd want to reserve 64 x 3 = 192 bytes of data (plus maybe a few extra bytes for control info, such as how many chunks are present: 2 or 3?). Then, as the USB frames come by, you'd put your 2 chunks or 3 chunks of data onto the wire, and the receiving end would then get that data, albeit in a more bursty way than just smoothly at a precise 2.5KHz rate. However, this way of transferring the data would more than keep up, even with USB 1.1, and still only use a fraction of the total available USB bandwidth.
The problem, as I see it, is whether your system design can tolerate a data delivery rate that is "bursty"... in other words, instead of getting 64 bytes at a rate of 2.5KHz, you'll be getting (on average) 160 bytes at a 1 KHz rate. You'll actually get something like this:
So, I think with USB that will be the best you can do -- get a somewhat bursty delivery of either 2 or 3 of your device's data packet per 1 mSec USB frame rep rate.
I am not an expert in USB, but I have done some work with it, including debugging a device-to-host tunneling protocol which used USB "interrupts", so I have seen this kind of implementation on other systems, to solve the problem of matching the USB frame rate to the device's data rate.

Control stepper motors via USB

I'm doing a USB device is to control stepper motors. I've done this before using a parallel port. because these ports do not exist in current motherboards, I decided to implement a USB communication between my device and the PC (host).
To achieve My objective, I endowed the freescale microcontroller the device with that has a USB module 12Mbps.
My USB device must receive 4 bytes (one for each motor driver) at a given time, because every byte is a step that should move the engine.
In the PC (Host) an application of user processes a text file with information and make the trajectory coordinates sending bytes at a certain rate for each motor (time is trivial to achieve the acceleration and speed of the motors) .
Using the parallel port was an easy the task because each byte is sent sequentially to a time determined by the user app.
doing a little research about full speed USB protocol understood that the frame is sent every 1ms.
then you can send 4 byte or many more every 1ms but I can not manage time like I did with the parallel port.
My microcontroller can send up to 64 bytes per frame (Based on transfer papers type Control, Bulk, Int, Iso ..).
question 1:
I want to know in what way I can send 4-byte packets faster than every 1 ms?
question 2:
What type of transfer can advise me for these type of devices?
Thanks.
Like Ricardo said, USB-serial will suffice.
As for the type of transfer, try implementing a CDC stack and use your SCI receiver to listen for PC commands. That will give you a receive buffer which will meet your needs.
Initialize your SCI (baud, etc)
Enable receiver and interrupt
On data receive, move it to your 4-byte command buffer
Clear receive buffer, wait for more
When you have all 4 bytes, fire off the steppers! Four bytes should take µs.
Check with Freescale to see if your processor is supported.
http://cache.freescale.com/files/microcontrollers/doc/support_info/USB_STACK_RELEASE_NOTES_V4.1.1.pdf?fpsp=1
There might even be some sample code to get you started.
-Cheers
I am achieving the same goal (driving/control CNC machines) like this:
the USB device is just synchronous I/O parallel port. Using continuous bulk transfer one pipe as input and one as output. This way I was able to achieve synchronous 64bit parallel communication with ~70KHz sample rate. It uses traffic around (i)4.27+(o)4.27 MBit/s that is limit for mine MCU and code. Bigger speeds cause jitter on the output due to USB events interrupts.
How to do it (on MCU side)
I have 2 FIFO's one for ingoing and one for outgoing data. I have timer interrupt occurring with sample rate frequency. In it I read the inputs and feed it to the first FIFO and read data from the other FIFO and send it to the outputs.
On top of that the USB task is called (inside the same interrupt) checking FIFO for sending to and incoming data from USB handling the transfer itself
I choose ATMEL AT32UC3A chips for this task. After a long and pain full research I decided these MCU's because they have enough memory for both FIFO's and program so no need for additional IC. It has FPGA package which can be used (BGA is not an option). It has HS USB (most USB MCU's have only FS like yours). It runs at 66MHz. It supports many interesting features (did interesting projects with it in the past) and of coarse I have experience with ATMEL MCU's from past
So if you want to achieve something similar then
start with bulk transfer (PC -> USB -> MCU -> output)
add FIFO if needed
do not know the sample rate you need. The old LPT's could handle from 80-196KHz depend on the manufactor. The modern ones are much much slower (which is silly and sad).
measure the critical sample rate
you need oscilloscope or very good hearing for this. The output data must be synchronous so no holes in it, no jitter, etc...
if any of these are present you have to lower the sample rate. Mine setup could handle even 1MHz sample rate but the USB jitter was present (sometimes USB event froze the sending for longer that one sample...) so I achieve only 70KHz of stable output.
if needed also inputs then add them
but only if the output is working as it should. Do not forget to lower the sample rate after this too ... Use separate bulk pipes and FIFOs for input and output.

Synopsys USB OTG Controller (2.65a) occasionally truncates isochronous IN in USB device mode

I'm using a Synopsys OTG core in device mode. Programming an isochronous IN high speed endpoint (USB 2.0) for the maximum transfer per microframe (3 packets of 1024 bytes) using a periodic FIFO dedicated to this endpoint. It works 99+% of the time. But occasionally the transfer is truncated. For example, the first 1024 bytes will go onto the bus with the DATA0 PID (instead of the correct DATA2 PID) and the remaining 2048 bytes will not be sent. Since I've programmed the packet count, multicount, max packet size and transfer size correctly I'm not sure what is causing this.
Obviously this is a very specific question and I don't have much hope of getting an answer, but I figured a shot in the dark was worth a try. Thanks in advance.
Isochronous transfers does not guarantee packet delivery. So if host controller has other active transfers, it will silently drop isochronous packets. If you need guaranteed packed delivery, you should use bulk transfers (but then it will not guarantee delivery time).
Isochronous is ideal for applications, like sound or video streaming, where you need constant delivery time, but loss of some frames is ok.
The specification places limits on the bus, allowing no more than 90% of any frame to be allocated for periodic transfers (Interrupt and Isochronous) on a full speed bus. On high speed buses this limitation gets reduced to no more than 80% of a microframe can be allocated for periodic transfers. (c) http://www.beyondlogic.org/usbnutshell/usb4.shtml
Answering my own question in case it may help someone else. It appears this OTG controller has a bug where the TX FIFO does not always empty properly. I found a successful workaround is to flush the FIFO after each TX. It's quick and the truncation symptom goes away.

Faster USB HID output

I'm attempting to speed up a rather sluggish bootloader. Currently I'm sending data on a single USB HID output endpoint, and as it's a low-speed device I'm apparently limited to one 8-byte packet per 10 ms interval for a whopping 800 bytes/second.
Is it possible to increase the reporting frequency somehow? Or to use multiple output endpoints in a single interface or as part of a composite device? Or perhaps to abuse the control endpoint to send additional data?
Better compression is always an alternative I suppose, but it's an area of diminishing returns, and redesigning the hardware to allow full-speed USB isn't really an option.
For the record I'd be happy with a Windows-only solution.
Or perhaps to abuse the control endpoint to send additional data?
You can use "Vendor specific requests" for that. The TI TUSB3410 Chip works that way AFAIK. Many USB stacks have the hooks for them already in place.
This requires a driver or libusb on the host side, however.
I was able to speed up the upload by orders of magnitude by using SET_REPORT requests on the control endpoint, instead of declaring a separate interrupt out endpoint. That way you get all of the bandwidth available for control transfers.
Also using a larger report split into multiple segments helped reduce the number of SETUP packets needed.
Who says you are limited to an 8-byte packet per 10ms? I don't know the exact numbers off the top of my head, but I know you can send larger packets than that. I did an HID device and was using 64-byte packets. I think I could go larger, but that limit is probably hardware-specific. What hardware are you using?
Also, have you consulted USB in a NutShell?
The actual limit is 8 bytes every 10ms for low-speed devices, and 64 bytes every 1ms for high-speed devices, per interrupt-based endpoint.
So it seems that the first thing to try is switching to high-speed mode, if the hardware supports it. The next thing on the list is using multiple endpoints. If you really want to get the highest possible transfer rate, the HID class is a bad choice.