First, let's take a look at the working process of USB.
When a USB device is connected to the host, the host begins to enumerate the USB device and sends instructions to the USB device to obtain relevant description information of the USB device, including device description (device descriptor), configuration description (configuration descriptor), interface description (interface descriptor), endpoint description (endpoint descriptor), etc. This information is transmitted to the host through endpoint 0 (endpoint 0). After obtaining various description information, the operating system will configure corresponding resources for it. In this way, the host can communicate with the device.
There are four communication modes of USB communication: control, interrupt, bulk and synchronous. USB communication is implemented through pipes. Pipes are an abstract concept, referring to the virtual link for communication between the host and the device. For example, a USB communication host A and device B, there are three communication modes: bulk in (batch input), bulk out (batch output), and control out (control output), then there are three communication pipes between A and B. (Here is a clear concept. In USB communication, the data flow direction is relative to the device. In means that the device transmits data to the host, and out means that the host box device transmits data). On the device side, each pipe corresponds to an endpoint, and the endpoint configures the relevant registers and buffers. Before communication, the endpoint needs to be set up. During communication, you only need to write or read data to the buffer and set the relevant bits.
The following specifically describes the USB interface microcontroller program design of stm32 based on the keil C mdk development environment from the perspective of USB interrupt input and output. It is worth mentioning that st or related companies provide us with many encapsulation functions and related examples. We can modify them according to the examples to realize the USB communication program we need.
1. USB descriptor configuration
From the above description, it can be seen that the USB descriptor is the premise of USB communication. The host must first understand the device before it can communicate with it. In the examples provided by st, the descriptors are defined in the usb_des.c file. The following is an example of the Joystick to illustrate the configuration of the USB descriptor.
1.1 Device descriptor
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
0x12,
USB_DEVICE_DESCRIPTOR_TYPE,
0x00,
0x02,
0x00,
0x00,
0x00, 0x40,
0x84
,
0x19,
0x06,
0x04,
0x00,
0x02,
1,
2,
3,
0x01
}
The two important parameters of the device descriptor are the manufacturer ID and the product ID. The host will select the corresponding driver for the device based on the above two IDs. In our application, we generally only need to modify the two parameters in the example to complete the setting of the device descriptor.
1.2 Configuration descriptor
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
0x09,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
JOYSTICK_SIZ_CONFIG_DESC,
0x00,
0x01,
0x01,
0x00,
0xE0,
0x32,
0x09,
USB_ INTERFACE_DESCRIPTOR_TYPE,
0x00,
0x00,
0x02,
0x00,
0x00,
0x00,
0,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x81,
0x03,
0x08,
0x00,
0x20,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x01,
0x03,
0x40,
0x00,
0x20,
}
The configuration descriptor includes the configuration of the interface and endpoint. If the device is a HID device, the HID description should also be added to the configuration descriptor. The specific description can refer to the configuration of the Joystick example.
There are some other configurations that can be understood by referring to relevant materials and examples.
2. The execution process of USB communication.
First, when the host data is transmitted to the USB device, how does the USB receive commands and data? The USB will first generate an interrupt. This interrupt is defined in the USB_HP_CAN_TX_IRQHandler and USB_LP_CAN_RX0_IRQHandler of the stm32fxxx_it.c file. Generally, USB_LP_CAN_RX0_IRQHandler is used. In this function, the USB_Istr() function is continued to be called. This function is the key to USB communication. It receives the host command and assigns the corresponding function to process it. For this point, I don’t understand the detailed process yet. If I understand it later, I will explain it again.
When a USB device is connected to the host, the host will enumerate the USB device and ask the USB device to provide relevant information about itself, which is achieved through endpoint0. Endpoint0 is a special endpoint, and each interface must have endpoint0. Generally, we need to use multiple endpoints (as mentioned above, the configuration descriptor defines the number, type, transfer data size, etc. of the endpoint). The endpoint needs to be initialized before use. This process is defined in the xxx_reset() function in the usb_prop.c file. For example, I define two transmission modes for endpoint 1:
SetEPType(ENDP1, EP_INTERRUPT);
SetEPRxAddr(ENDP1, ENDP1_RXADDR);
SetEPRxCount(ENDP1, 8);
SetEPRxStatus(ENDP1, EP_RX_VALID);
SetEPType(ENDP1, EP_INTERRUPT);
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
SetEPTxCount(ENDP1, 64);
SetEPTxStatus(ENDP1, EP_TX_NAK);
After defining the endpoint, we can use the endpoint for data transmission.
Input data to the host (in): The IN transmission process is
1. Fill the buffer with data;
2. Set the USB data counter:
3. Set the USB output to be valid.
XXX_send()
{
UserToPMABufferCopy(sendBuffer, ENDP1_TXADDR, 2);
SetEPTxCount(ENDP1, 2);
SetEPTxValid(ENDP1);
}
Note that in general, the input and output buffer addresses of the endpoint are not defined and must be defined in usb_conf.h. For specific definitions, please refer to the definition of endpoint 0.
Read data output from the host (out): The out transmission process is
1. Define the out callback function;
2. Read data from the buffer:
3. Set USB input valid.
void EP1_OUT_Callback(void)
{
u8 DataLen;
DataLen = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(rcvData, ENDP1_RXADDR, DataLen);
SetEPRxValid(ENDP1);
}
Note that in general, the declaration of the EPX_OUT_Callback() callback function is an empty execution function. #define EPX_IN_Callback NOP_Process in usb_conf.h needs to be hidden. Then redefine void EP1_OUT_Callback(void) in the appropriate place (the appropriate place means that after the definition, there will be no error that EP1_OUT_Callback is not declared when running).
In summary, the USB communication of the STM32 chip is briefly explained here. My level is limited, and there are inevitably mistakes in the above. I hope everyone will leave a message actively, discuss together, and make progress together. This article was written intermittently, which brought inconvenience to everyone. I apologize to everyone here. Anyway, I hope this article can be of some help to those friends who are still exploring the initial stage of STM32USB programming.
Keywords:STM32
Reference address:STM32 USB design principles
1. USB descriptor configuration
1.1 Device descriptor
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
}
The two important parameters of the device descriptor are the manufacturer ID and the product ID. The host will select the corresponding driver for the device based on the above two IDs. In our application, we generally only need to modify the two parameters in the example to complete the setting of the device descriptor.
1.2 Configuration descriptor
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
}
There are some other configurations that can be understood by referring to relevant materials and examples.
2. The execution process of USB communication.
SetEPType(ENDP1, EP_INTERRUPT);
SetEPRxAddr(ENDP1, ENDP1_RXADDR);
SetEPRxCount(ENDP1, 8);
SetEPType(ENDP1, EP_INTERRUPT);
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
SetEPTxCount(ENDP1, 64);
SetEPTxStatus(ENDP1, EP_TX_NAK);
After defining the endpoint, we can use the endpoint for data transmission.
Input data to the host (in): The IN transmission process is
1. Fill the buffer with data;
2. Set the USB data counter:
3. Set the USB output to be valid.
XXX_send()
{
UserToPMABufferCopy(sendBuffer, ENDP1_TXADDR, 2);
SetEPTxValid(ENDP1);
}
Note that in general, the input and output buffer addresses of the endpoint are not defined and must be defined in usb_conf.h. For specific definitions, please refer to the definition of endpoint 0.
Read data output from the host (out): The out transmission process is
1. Define the out callback function;
2. Read data from the buffer:
3. Set USB input valid.
void EP1_OUT_Callback(void)
{
u8 DataLen;
DataLen = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(rcvData, ENDP1_RXADDR, DataLen);
SetEPRxValid(ENDP1);
}
Previous article:stm32 usb enumeration process
Next article:stm32 usb data buffer question
- Popular Resources
- Popular amplifiers
Recommended Content
Latest Microcontroller Articles
He Limin Column
Microcontroller and Embedded Systems Bible
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
MoreSelected Circuit Diagrams
MorePopular Articles
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
MoreDaily News
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
Guess you like
- Infringement! Chinese company demands 10-year ban on iPhone sales and 10 billion RMB in damages
- Can stm32 separate the kernel from the application (using dynamic link libraries?)
- [CY8CKIT-149 PSoC 4100S Review] + Unboxing
- [NUCLEO-L452RE Review] + Serial Communication and Component Control (and Final Report)
- Why does LSM6DSOX INT2 remain high after triggering the interrupt?
- How to use ftp to update demo
- [NXP Rapid IoT Review] + Summary of Bluetooth protocol stack usage
- [TI recommended course] #[High Precision Laboratory] Introduction to Data Converters#
- PS1 Modchip using micropython
- IMX283 can't be sent out