Host environment: Windows 7 SP1
Development environment: MDK5.18
Target board: STM32F103C8T6
Development library: STM32F1Cube library and STM32_USB_Device_Library
Continuing with yesterday's study notes, it was mentioned before that there was no data loss when comparing the data captured from the USBTrace software with the original image data. It was just that half of the data packets had errors during the transmission process, which resulted in us being unable to obtain normal images on the PC, and thus displaying a black screen all the time. This reason took a long time to find, and we were impatient and would do other things after debugging for a while. For debugging, analyzing the problem points can better solve the problem. You can think about why half of the data packets are wrong, not individual data packets, nor one-third, one-quarter, etc., and think of the double buffering feature enabled in synchronous transmission in STM32. Only this feature is related to one-half of our error points. Therefore, it is very likely that there is a problem with the double buffering here. Now the question is, about STM32 The double buffer transmission feature of synchronous transmission is not related to it in the upper layer application. Our transmission function only uses the USBD_LL_Transmit() function, so we start from this function and finally enter the USB_EPStartXfer() function in the stm32f1xx_ll_usb.c file. In this function, we write the data to PMA as follows:
If DTOG_TX is set, DBUF1 is accessed, otherwise DBUF0 is accessed. For the double buffering mechanism of USB in STM32, you can read the USB chapter of STM32F103C8T6 reference manual, which will explain in detail. We know that STM32 USB provides 8 bidirectional endpoints, and if an endpoint enables the double buffering mechanism in a certain direction, the TX and RX areas are managed by the same direction. You can see the example of packet buffer as follows:
The key point is to look at the buffer of IN endpoint 3 in double buffer mode. At this time, the RX area is taken over by TX_1. In the code, the addresses of TX_0 and TX_1 are specified, and the length of the data to be sent in this buffer is specified by PCD_SET_EP_DBUFx_CNT(). Tracing back the definition of PCD_SET_EP_DBUFx_CNT(), the problem is found as follows:
#define PCD_SET_EP_DBUF0_CNT(USBx, bEpNum, bDir, wCount) { \ if((bDir) == PCD_EP_DBUF_OUT)\ /* OUT endpoint */ \ {PCD_SET_EP_RX_DBUF0_CNT((USBx), (bEpNum),(wCount));} \ else if((bDir) == PCD_EP_DBUF_IN)\ /* IN endpoint */ \ *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ } /* SetEPDblBuf0Count*/ #define PCD_SET_EP_DBUF1_CNT(USBx, bEpNum, bDir, wCount) { \ if((bDir) == PCD_EP_DBUF_OUT)\ {/* OUT endpoint */ \ PCD_SET_EP_RX_CNT((USBx), (bEpNum),(wCount)); \ } \ else if((bDir) == PCD_EP_DBUF_IN)\ {/* IN endpoint */ \ *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ } \ } /* SetEPDblBuf1Count */ It can be seen that the buffer length settings of these two IN endpoints actually use the same interface--*PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); So this is where the problem lies. The interface definition is as follows: #define PCD_EP_TX_ADDRESS(USBx, bEpNum) ((uint32_t *)(((USBx)->BTABLE+(bEpNum)*8)*2+ ((uint32_t)(USBx) + 0x400))) #define PCD_EP_TX_CNT(USBx, bEpNum) ((uint32_t *)(((USBx)->BTABLE+(bEpNum)*8+2)*2+ ((uint32_t)(USBx) + 0x400))) #define PCD_EP_RX_ADDRESS(USBx, bEpNum) ((uint32_t *)(((USBx)->BTABLE+(bEpNum)*8+4)*2+ ((uint32_t)(USBx) + 0x400))) #define PCD_EP_RX_CNT(USBx, bEpNum) ((uint32_t *)(((USBx)->BTABLE+(bEpNum)*8+6)*2+ ((uint32_t)(USBx) + 0x400))) In the previous packet buffer example, we know that TX_1 is the taken over RX area, so DBUF1_CNT should use the PCD_EP_RX_CNT() interface instead of the PCD_EP_TX_CNT() interface. Therefore, ST's library code may not be intact. At least this problem has not been fixed. Modify the library code as follows: #define PCD_SET_EP_DBUF0_CNT(USBx, bEpNum, bDir, wCount) { \ if((bDir) == PCD_EP_DBUF_OUT)\ /* OUT endpoint */ \ {PCD_SET_EP_RX_DBUF0_CNT((USBx), (bEpNum),(wCount));} \ else if((bDir) == PCD_EP_DBUF_IN)\ /* IN endpoint */ \ *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ } /* SetEPDblBuf0Count*/ #define PCD_SET_EP_DBUF1_CNT(USBx, bEpNum, bDir, wCount) { \ if((bDir) == PCD_EP_DBUF_OUT)\ {/* OUT endpoint */ \ PCD_SET_EP_RX_CNT((USBx), (bEpNum),(wCount)); \ } \ else if((bDir) == PCD_EP_DBUF_IN)\ {/* IN endpoint */ \ *PCD_EP_RX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ } \ } /* SetEPDblBuf1Count */ Then recompile the code and burn it into the board. After running it, we finally get the image we want. The result is as follows:
Then recompile the code and burn it into the board. After running it, we finally get the image we want. The result is as follows:
The image is a little smaller. You can change it to a larger image. So far, the simple UVC transmission of MJPEG using STM32's USB has ended. The first step of the Long March has been completed. Now we can proceed to the next step of studying MJPEG encoding or studying the transmission of other load formats. After all, we are too static when transmitting a single picture. If we study the encoded image, it can be animated and more intuitive. MJPEG is based on frame format transmission, which is easier to learn. There are also some stream-based formats. You can study them when you have time. The UVC document mentions 8 load formats. If you are interested, you can try them one by one. At the same time, there are some other features in the UVC protocol that are not used here, such as: image capture, and some control requests. The document also mentions that not only synchronous transmission can be used to transmit video, but also batch transmission can be used to transmit video. Many features of UVC are waiting to be explored. Finally, our UVC library needs to be improved. It can be improved to an interface equal to that of AUDIO, CDC, HID, and MSC libraries for easy use.
Below is the project code download address: http://download.csdn.net/detail/key123zhangxing/9551843
PS: The code uploaded yesterday was not cleaned up, and there will be errors when compiling. You need to remove the uart_init() function call in main.c and the uart.h header file included in the main.h file.
Previous article:STM32 USB HID custom device bulk transmission
Next article:STM32F4-DISCO learning DMA double buffer mechanism
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- 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
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- I encountered several problems in the multisim simulation of the bandpass filter circuit, as shown in the figure. Which forum friend can give me some advice?
- I would like to ask for some knowledge about voltage regulator diodes
- Android BLE low-power Bluetooth slave device application
- Intel FPGA Authoritative Design Guide
- How to download routines to TMS320F28377S in ccs7.4? I hope there are detailed steps
- DWIN 86 box hardware development information sharing
- Msp430F5438A interrupt initial
- EEWORLD University - Teach you how to use emWin graphical interface
- Chuanglong TMS320C6748 development board——timer/counter learning
- The Android software has been unable to successfully upload the example to the board. Is this a bug?