STM32 UVC study notes 3

Publisher:诚信与爱Latest update time:2018-09-20 Source: eefocusKeywords:STM32  UVC Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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.


Keywords:STM32  UVC Reference address:STM32 UVC study notes 3

Previous article:STM32 USB HID custom device bulk transmission
Next article:STM32F4-DISCO learning DMA double buffer mechanism

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号