cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4xx CubeMX USB device CDC class example

krubow
Associate II
Posted on September 26, 2014 at 02:00

I am using an STM32F427 processor and wish to implement a USB device CDC virtual serial port on the HS USB port. I am generating my initialization/driver code with CubeMX. I am having a hard time figuring out what needs to be implemented in the usbd_cdc_if.c file to get buffered full duplex data transfer. I do not want a USB/USART bridge, just communication via a virtual serial port to the embedded application.

Any CubeMX generated examples projects out there? I use the USB HS because the FS is preempted by the USART1 RTS/CTS pins. I need flow control to work in both directions, and would also like to know when the virtual COM port is opened or closed on the PC end. Is this done through CDC_Control_HS, or by monitoring the device status is some other way?

There doesn't seem to be any written documentation on the USB device driver, or maybe there is but I don't know where to find it?

10 REPLIES 10
Posted on September 30, 2014 at 18:22

Hi rubow.keith,

To have more insight into the USB libraries using the STM32Cube library please check the USB_Device applications within the

http://www.st.com/web/en/catalog/tools/PF259243#

package.

You can refer also to the following document:

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00108129.pdf

Regards,

Heisenberg.

krubow
Associate II
Posted on October 09, 2014 at 01:58

OK, I have a working CDC driver, and I can establish a communication session to my application via Hyperterminal or Teraterm running on a PC, connecting through a virtual COM port. My only problem right now is flow control of data sent from the PC to my application running on the ARM. I am using the HS usb interface in device only mode. I receive data from the PC host by transfering the data to my receive buffer in the CDC_Receive_HS function in usbd_cdc_if.c. But if I don't process the data before another packet arrives, data is lost. The comment for the CDC_Receive_HS function says I should not return from this function until the received data packet is processed. But isn't the CDC_Receive_HS function called from an interrupt service routine? I am running a cooperative multi-tasking system, and other tasks will process the data from my receive data buffer. I can't call nextask() to relinquish control of the processor to the next task from within an interrupt service routine. How do I block reception of further packets from the host until I am ready to receive more data?

tsuneo
Senior
Posted on October 09, 2014 at 08:07

> How do I block reception of further packets from the host until I am ready to receive more data?

I’m looking in this example,

\STM32Cube_FW_F4_V1.3.0\Projects\STM324xG_EVAL\Applications\USB_Device\CDC_Standalone

And you seem to talk about a template generated by CubeMX. And then, the function name on my comment is a little different from yours. Anyway, the code flow should be the same.

In above example, the ''USBD_CDC_ItfTypeDef.Receive'' callback of the bulk OUT endpoint is registered as CDC_Itf_Receive(). Though I’ve traced the stack source around this routine up to the ISR origin, there is no sign which causes overwrite to the hcdc->RxBuffer.

Overwrite should occur, when another USBD_CDC_ReceivePacket() call would be made by your firmware, before your ''Receive'' callback could consume the data on the RxBuffer completely. In above example, USBD_CDC_ReceivePacket() is called by HAL_UART_TxCpltCallback() (usbd_cdc_interface.c).

Find USBD_CDC_ReceivePacket() call in your template, and tune the code, so that it should not be called before the ''Receive'' callback consumes all of the data on the buffer.

Tsuneo

krubow
Associate II
Posted on October 10, 2014 at 00:29

Thank you for your suggestions. Based on other sample projects I had found online, I was already calling USBD_CDC_ReceivePacket in my application code after processing the complete data buffer. So I dug deeper and did some more debugging. I found I was not actually receiving packets faster than I could process them, rather I am receiving duplicate packets! Through some additional debug code I was able to keep a history of all characters received from the host PC, and also a history of the sizes of the received data packets.

My application communicates with a PC via TeraTerm over a virtual serial port. I type a few characters on the PC keyboard to select some commands from a menu in my application, then I use TeraTerm to send an Intel HEX file to my application (sent as a plain text file). The data received by my application consists of a total of 8 packets before I encounter an error condition and stop at a breakpoint. The first 6 packets are all 1 byte in size, and are the six characters I type on the keyboard to prepare my application to receive the Intel HEX file. The 7th packet is 64 bytes long, and contains the first 64 characters of the file sent by TeraTerm. The 8th received packet is also 64 bytes long, and is a DUPLICATE of the 7th packet. My application sees the first 64 bytes of the file TWICE.

So is this a bug in my ARM application, a bug in the USB driver code from StMicro, or a bug in the virtual COM port driver software from StMicro?

FYI, my ARM application can send data TO the PC really fast, and the data appears to be received my the PC perfectly every time. Anyone have an idea where I should look?

Posted on October 10, 2014 at 13:42

Hi rubow.keith,

Can you please provide us your project source files so that we reproduce the limitation you are experiencing ?

Regards,

Heisenberg.

tsuneo
Senior
Posted on October 10, 2014 at 16:09

> The 8th received packet is also 64 bytes long, and is a DUPLICATE of the 7th packet. My application sees the first 64 bytes of the file TWICE.

Sound like TeraTerm cancels the last transfer, and it re-sends the packet, because of timeout. Are you using ZMODEM?

> So is this a bug in my ARM application, a bug in the USB driver code from StMicro, or a bug in the virtual COM port driver software from StMicro?

To answer to this question, you may apply COM packet monitor and software sniffer at the same time.

COM port packet monitors cut in to the traffic between PC application (TeraTerm) and the driver APIs. USB software sniffers peek the traffic between PC driver (usbser.sys) and low-level system drivers.

COM packet monitors

- PortMon (just for x86 Windows)

http://technet.microsoft.com/en-us/sysinternals/bb896644.aspx

- API Monitor (works on x64, too)

http://www.rohitab.com/apimonitor

check ''Data Access and Storage'' and ''Devices'' filter, to capture activity on COM port.

USB sniffers

Free USB Analyzer  http://freeusbanalyzer.com

USBlyzer (commercial, 33 days trial) http://www.usblyzer.com/

USBTrace (commercial, 15 days trial) http://www.sysnucleus.com/

etc

If you would see the duplicate packet on COM packet monitor, TeraTerm should send it.

IF both of these monitors wouldn’t see the extra packet, it could be made on your device.

Tsuneo

krubow
Associate II
Posted on October 13, 2014 at 18:28

Attached is a ZIP archive of my project. It is an Atollic TrueStudio project. I created the ZIP using the Atollic Export wizard. It should include all libraries used by the project.

For debugging I had logged all received characters into a temporary buffer in function _getch in main.c. I had also logged the sizes of all received data packets into a temporary buffer in function CDC_Receive_HS in usbd_cdc_if.c. This debug logging code is not currently in the project, but I'm sure you an add it easily enough. I hope you can run this code without my target hardware board. It runs on an STM32F427ZIT6, currently set up to run in the second flash memory bank. I receive a duplicate 64 byte block of data from the PC host running TeraTerm 4.78 running on my Windows 8.1 system when TeraTerm is told to SEND a simple ASCII text file to my application.

Let me know if you need any more details about my project, or duplicating the error.

________________

Attachments :

Cwr24e.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0Fu&d=%2Fa%2F0X0000000bci%2Frtt0yPSdmfvSQDVubrrVl3U17U4AJd28Dh_ICDXcoLY&asPdf=false
Posted on October 17, 2014 at 17:49

Hi,

Your project header files are missed for HAL, USB stack and application. Please try to upload a complete compressed project.

PS: Avoid using Atollic Export wizard. It may be the root cause.

Regards,

Heisenberg.

krubow
Associate II
Posted on October 29, 2014 at 22:17

I have attached a ZIP file of my entire project folder located under my Atollic workspace. It should contain all of my source and header files. Of course, Eclipse uses those funny virtual folders with links to files in the host filesystem. All of the ST Micro library files, header files, startup files, etc. exist in my project as links. The absolute locations of these files may be different on your system. Eclipse projects with linked resources are not very portable across different computers, are they?

To clarify, I an sending a simple text file from Tera Term (no Xmodem or Zmodem protocol, just send text file). I end up receiving the first 64 byte packet over the USB port TWICE. Characters typed on the keyboard come at a much slower rate, and that works fine. But Send Text File, and I get a duplicate data packet right away.

Let me know what else I can do to help track down this problem. It could be in the USB device driver in the ARM. I could be in the Windows Virtual COM port driver. It could be in my ARM application if I am doing something wrong. I doubt very much that it could be in Tera Term. I have used Tera Term to send text files over a virtual USB serial port using an FT245RL USB to parallel chip (which acts as a CDC device), and never experienced this problem.

Keith

________________

Attachments :

Cwr24a.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0Tg&d=%2Fa%2F0X0000000bch%2FBJ2wbXB6d1hGYFgUZt1wPtr7MwhH93bAfkGMPuB_n9Q&asPdf=false