cancel
Showing results for 
Search instead for 
Did you mean: 

Losing data over USB with a modified VCP example

mislav
Associate
Posted on June 10, 2014 at 20:46

Hello,

I need to establish USB communication between an STM32F405 device and a PC. STM sends 152 bytes of data every 2.3 miliseconds, but there are also some other events and data that should occassionally be sent in either one or both directions. The problem is, some of those regular 152-byte packets (sometimes after only hundreds, sometimes after tens of thousands of successful packets) lose a chunk. And when I try to send a big 412-byte packet from PC to STM, it always completely loses the front part.

The PC side of the code should be cross-platform and I was looking for something simple to implement (since this is my first USB device) so I just adapted the VCP example code for the STM. That allows me to use Boost Asio library on PC (exact code used is 'CallbackAsyncSerial' from this link: http://www.webalice.it/fede.tft/serial_port/serial_port.html).

I removed all the USART code from the VCP example, but I don't believe that's where the problem is. I also changed a few settings: enabled the HS core (in FS mode), increased the buffer size (APP_RX_DATA_SIZE) to 4096 and eliminated the interval between IN transfers (CDC_IN_FRAME_INTERVAL = 0).

Lastly, I enabled the internal DMA. This didn't compile at first because a 'usbd_cdc_Desc' array was missing. I think that's a bug, so I just created it by copying a chunk out of 'usbd_cdc_CfgDesc'. I also don't think 'USB_CDC_DESC_SIZ' is defined correctly.

I would be really grateful if someone could offer assistance. I just don't know where the problem could be.

#stm32f4-usb-cdc-device
2 REPLIES 2
chen
Associate II
Posted on June 11, 2014 at 10:10

Hi

Without looking at your code - I can only guess at what might be causing you problems.

On the forum, a few people have asked about data through put on USB CDC.

I do not think anyone has complained about Pc-to-STM32 data through put, mainly

STM32-to-Pc

In any case, it may be related. Have a look at the file usbd_cdc_core.c

It uses a data buffer and related pointer ; look for

APP_Rx_Buffer[]

APP_Rx_ptr_in

APP_Rx_ptr_out

APP_Rx_length

The function Handle_USBAsynchXfer() actually handles the transfer of data in/out of the USB peripheral.

I do not know where DMA comes into this, I have not looked at DMA functionality in the USB peripheral driver.

FYI, I have experienced data throughput problems on the PC side. Using the standard windows/MS CDC device driver (which is what the ST CDC driver installs), it appears there is a 100ms period between USB packets. I measured this by instrumenting the Handle_USBAsynchXfer() function and saw that it only triggers at 100ms intervals. So there may be a issue with the PC driver.

mislav
Associate
Posted on June 11, 2014 at 21:47

Thanks for giving me a good place to start looking. I managed to solve both of my problems.

Device-PC transfers actually worked just fine all along. What was wrong with them is one of the most unexpected software flaws I've seen. When you're monitoring the console output of a program in Visual Studio, you will actually block program execution while you drag the scroll bar. That made the input buffer overflow. So I just stopped scrolling and now it works.

PC-device transfers also actually worked, I just didn't handle the received data well. It was a stupid bug that I should have noticed a lot sooner and I shouldn't have bothered the forums.

Just so I don't feel like I've wasted a whole day for nothing, here are my conclusions about the things you mentioned.

'Handle_USBAsynchXfer()' function gets called every 'CDC_IN_FRAME_INTERVAL+1' SOF interrupts (which happen once every 1 ms). Since it's linked to SOF, the only way to get it called every 100 ms is by setting 'CDC_IN_FRAME_INTERVAL' to 99. It also only seems to start IN transfers on endpoint 1 (if they aren't already running). If the transfer cannot be handled in just one packet, the rest of them are sent in the 'usbd_cdc_DataIn()' function.

'usbd_cdc_DataOut()' handles the OUT transfers on endpoint 1. It gets called every time a new packet is received.

I also think maybe 'usbd_conf.h' has a bug. When choosing max packet size, the CDC in frame interval etc., it only checks if the HS core is enabled. Shouldn't it instead check if HS mode is enabled? Perhaps with '#if defined(USE_USB_OTG_HS) && defined(USE_ULPI_PHY)'? Because as it is, it will set 512 B max packet size if you are using the HS core in FS mode. Is that even possible? I really don't know how the USB protocol works, only the bare basics.