cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 USB custom class

Mehran Memarnejad
Associate III

Hi,

I want to use my own custom usb device class base on usb core provided by ST. Inspecting the code, I found that "DataIn" and "DataOut" callback functions provided by the class to usb core are called at the END of the data in or out stage... Calling DataOut callback at the end of the data out stage is good as all of the received data is available, But for the DataIn, I want to be notified the at the START of data in stage, i.e. be notified that an IN packet received and then send my own data over it ... I guess "ITTXFE: IN token received when Tx FIFO is empty" interrupt for IN endpoints can help me, But that's not triggered when I send an IN packet over endpoint2 (I can see IN packet in wireshark coming out of my PC to STM32)

How can I do that??

1 ACCEPTED SOLUTION

Accepted Solutions
Mehran Memarnejad
Associate III

I used the following trick to get notified:

1- Set EndPoint's nack bit

2- Enable Nack interrupt for that EndPoint

3- Upon receiving new request, as the nack bit was set, nack interrupt will be triggered and in the ISR, I will call my callback

View solution in original post

5 REPLIES 5
Mehran Memarnejad
Associate III

I used the following trick to get notified:

1- Set EndPoint's nack bit

2- Enable Nack interrupt for that EndPoint

3- Upon receiving new request, as the nack bit was set, nack interrupt will be triggered and in the ISR, I will call my callback

MVENN.1
Associate II

Hi

I'm also working on same like to create the custom class usb in stm32.But I'm able do this one. Mainly in device manager shows the usb name as a separately but I'm not getting can you please suggest me.

thank you.

Hi MVENN.1,

I didn't understand what your problem is. Could you please give more information? What can't you get?

MVENN.1
Associate II

HI

I'm facing the problem, How to create our own custom class usb in stm32f439zi development board?

could you please suggest.

Hi,

Before anything else, Remember that: USB is a complex protocol compared with UART, I2C, SPI and etc. It's good to know everything about it, but you don't need to know all details for simple works.

In USB world, we have two kinds of device:

1- Single function devices: These are devices that have a single function, e.g. a printer, a camera and etc

2- Composite devices: These are one PHYSICAL device but contains multiple LOGICAL devices, e.g. a webcam (physical) which can record both audio and video (logical)... It is as if this single PHYSICAL device is two separate device

When you connect your USB device, the HOST (e.g. your computer) will ask for its descriptors.

There are different kinds of descriptors such as device, interface, endpoint descriptors

In USB world, we have two kinds of classes:

1- Standard classes: like CDC, HID and etc that have support in operating systems, i.e. as they have standard functionality and commands, there drivers are available in common OSes such as Windows and Linux... For example, USB mouses use HID class and as their driver is available in OS, you don't need to install it...All mouse manufacturers will implement this HID class for their mouse... This the same for usb2serial convertors(CDC), external hard drives(Mass Storage class), microcontroller programmers(DFU class) and etc.

You can find descriptors for standard classes on Internet to get an idea how they implement their class

2- Custom classes: These are used for custom USB device... suppose that you want to build a USB device with some custom functionality that is not supported with standard classes

For your custom class, you need to develop two things:

***Firmware: the code implementing your class and runs on your MCU

***Device driver: the code running on your PC and interact with your device

To design your own custom USB device class, you need to provide its descriptor. As stated in USB protocol, custom classes need to use some specific numbers in some fields of descriptor (e.g. 0xFF)...See this link

In summary:

For your custom class:

On firmware side, you need to do two general things:

1- Provide your descriptors:

Suppose you want to build a webcam with video and audio capturing features.

You can say in device descriptor that I have TWO interface (one for video and another one for audio). In video interface descriptor, say I have one IN endpoint and in audio interface say that I have one IN endpoint... As our webcam will just send video and audio data to host, so we only have IN endpoint, BUT if we need to get some data from host, then we can say we have OUT endpoint... Then in endpoint descriptor of video, you can say for example its type is isochronous and its max packet size is X bytes and other info... The same for audio endpoint

To get an idea on how to provide these information in descriptors, you can inspect standard class descriptors

2- Implement functions in your code for interface operations: refer to example classes like CDC in ST's code... Note that you must customize these codes base on how you divided your device to interfaces and endpoints

On the PC side, you need to develop a driver to interact with your device. To develop USB device driver, you have two options:

1- Userspace driver: You can use Libusb library which has function to receive data from your webcam device ... For example, to get video data you can calim its interface with libusb functions, and then use its functions to get data from video endpoint... the same goes for audio inteface

2- Kernel driver: You can develop kernel modules to do the same as userspace driver in kernel... Note that in Linux, you can say that my driver support usb devices with this vendor ID (VID) and product ID (PID)... then when you plug in your device, the Linux USB subsystem will automatically ask for descriptors behind the scene and PER INTERFACE, it will call your driver' probe. If your driver's probe return 0, then this device will bind to your driver, else other drivers tha might support this device will call in turn to see if they support or not.... Again note that your driver's probe finction will be called per interface, in our webcam example, one time for video interface and another time for audio interface...

You can refer to Linux device drivers book and exsiting USB drivers in kernel source code to get an idea of how to develop a driver for your device

An interesting thing is that you can represent a device as some thing else. For example, when you connect your cell phone to PC, it shows a mass storage that you can see your files in it as if you have connected an external hard drive... How it is done? It's simple. Host will know about a device by inspecting its descriptor, so if a cell phone introduces itself as a mass storage in its descriptor, then Host will represent it as mass storage... The same is true when you connect Beaglebone and it shows an ethernet interface and mass storage... Our when you connect St's boards and it show a mass storage

Hope this help you and you help others in turn

Best regards