cancel
Showing results for 
Search instead for 
Did you mean: 

Low latency (<1 ms) data transfer from stm32f446re to PC using USB

AHadi
Associate II

Hi ST Community,

I am very new to programming STM32 MCUs. I am using a stm32f446re MCU to read 6 ADCs through SPI interface. I would like to send the ADCs' data (12x24 bits) through the built in USB in STM32 MCU to a PC at 1500 samples/s. I searched a lot and found the USB concept very confusing. I mainly do not know which USB class I have to use (HDI, CDC, Audio, etc.)? an how it should be configured.

I appreciate if someone can show the big picture on where I should start from or some example codes/useful links.

Thanks for the help in advance.

6 REPLIES 6
Danish1
Lead II

I don't think you will be able to transfer things by USB with such low latency (i.e. low overall delay).

But what you can do is collect a group of samples into a buffer, and send them all up together. This way the average throughput will be sufficient for your needs even though the latency will be longer than 1 ms.

You get to choose the size of the group - most efficient if you can fill or nearly-fill a standard USB buffer.

Hope this helps,

Danish

Bob S
Principal

What @Danish​  said. As a USB "device", you have almost no control over when the data is actually sent to the PC. The USB "host" controls/initiates all data transfers. Now, presuming that your software running on the PC is always trying to read data from your device, whatever you write to your USB buffers will be sent in the next millisecond interval (presuming 12MHz USB 1.1 compatible interface, for the higher speed interface you get sub-millisecond intervals). Your aggregate throughput to the PC will match you ADC sample rate, but the timing of any individual sample getting to the PC is indeterminate.

AHadi
Associate II

Thanks @Danish​  and @Bob S​  for your comments.

The ADC signals are to be used in the feedback loop of a realtime control application. I was planning to use the integrated USB2.0 in the MCU. Isn't it possible to use isochronous endpoints to achieve thie low latency I am looking for? Do you have any suggestions on how it could be achieved?

Bob S
Principal

You are still limited by the 1ms USB frame rate. I'm a little rusty on the details of USB 2.0, but at a quick glance it looks like in 480 MHz "high speed" mode, you get sub-frames at 125us intervals, which means you have an opportunity to send data every 125us. Even isochronous transfer relies on SOME buffering of each end. The down-side to isochronous transfers is (I think) that transmission errors are ignored. Unlike interrupt and bulk transfers, if the USB interfaces detect a CRC error on incoming data, there is no re-transmit of that packet of data. What you get is what you get and it may be corrupted. With audio streams that is usually no big deal, all you get is a small pop or mushiness in the sound.

So - *IF* you are running in USB 2.0 High Speed mode (for which I think you need an external USB PHY), you *MIGHT* be able to get 375us (3 micro frames) turn-around from ADC data in to control data back to the device. 3 micro frames because you need 1 to transmit the ADC data, <= 1 micro frame for the PC to process the data, and 1 to transmit the control data back to the device.

If you are using the built-in USB PHY, you will be operating at 12MHz (i.e. "Full Speed") and a 1 ms frame rate, so I suspect the minimum turn-around is 2ms.

It mostly doesn't really matter WHICH USB interface (HID, audio, CDC, disk drive, etc.) you choose. They all have the same basic USB transport limitation. Though some may have lower protocol overhead (which means less time spent getting the data into and out of the USB transport packets.

So see if your control loop can handle a 2ms time constant. If not, you will have to move the control code onto the STM32. Which might not be too bad - hardware floating point (single precision), DSP multiply-and-accumulate instructions and 180MHz clock can do a lot of stuff.

AHadi
Associate II

Thanks @Bob S​ for the detailed explanation. It helped me a lot developing a better understanding. Because I have a realtime control application, data needs to be sent in a time deterministic manner from the MCU to the PC. My research also shows that I have to use isochronous transfer, if I can reach the sample rate high enough, ignoring the transmission errors will not affect the control loop perfomance significantly. However, when I searched online, I got some conflicting numbers. I am confused if the isochronous frame rate on a USB FS is every 125 micro seconds or every 1 ms? It appears that interrupt transfer modes happens at every 1 ms interval but the isochronous frames happen every 125 micro seconds. So even on a USB FS, I might be able to get the 375 turn around? My understanding could be completely wrong though.

Also when I search, it appears that HID runs in interrupt mode (every ms) but CDC is in isochronous. Is that true? I am confused with which interface class should be used for an isochronous transfer.

Sorry if my questions are dumb, I am very novice but very passionate to learn.

Bob S
Principal

The only dumb question in one not asked. No worries.

CDC uses bulk transfers to the best of my knowledge, not isochronous.

Again, my knowledge of the details of high speed USB 2.0 is quite limited. In general, the advantage of interrupt transfers is that when you configure an interrupt end point, it reserves time slots in each USB frame (and high speed sub-frame if on a high speed link) for your data, whether or not you actually transfer any data during that frame. If you have a known throughput rate (it looks like you do), this may work for you. But isochronous will work also if you can tolerate the possibility of missing data.

The "frame rate" on USB 1,1 and 2,0 is always 1 ms (I don't know about USB 3). The "subframe" rate on "high speed" USB 2.0 is 125 us. "Full Speed" USB does not have microframes, only the 1 ms frame rate. I don't know if it is possible on "full speed" (12 MHz) USB to receive data and then turn around and transmit data in the same 1ms frame. You may have to run an experiment and see.

If it were me, I'd use interrupt transfers. That what I did for a long ago project that was passing compressed voice samples back and forth (and the compression algorithms could not telerate lost data).