Skip to main content
Graduate
January 28, 2025
Question

STM32U5G9ZJT6Q USB UVC: Increasing Valid Micro Packets in Isochronous Transfers with DCMI Data

  • January 28, 2025
  • 1 reply
  • 590 views

Hello,

I am working with the STM32U5G9ZJT6Q MCU to implement a USB UVC application. Here are the key details of my setup:

  • MCU: STM32U5G9ZJT6Q
  • System Clock: 160 MHz
  • USB PHY External Clock: 32 MHz
  • Data Source: DCMI captures data at 640x480 resolution in 8-bit format.
  • USB Configuration: Isochronous transfers for UVC video streaming.

The issue I am facing is that for each isochronous packet, only 30 micro packets contain valid data, while the remaining 98 micro packets (out of 128 total) are empty. This limits the overall data throughput.

I would like to understand how I can increase the number of micro packets with valid data in each isochronous packet to optimize data transfer performance.

Steps I have tried:

  1. Verified DCMI and DMA data reception – data appears to be received correctly.
  2. Adjusted isochronous max packet size (HS_MPS) but did not see a significant improvement.

Could this be related to:

  • USB descriptor configuration?
  • DMA/USB buffer handling?
  • Timing or bandwidth issues with the USB PHY or DCMI?

I am sharing zip file of the code for the reference.

Thank you in advance!

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    July 17, 2025

    Hi @saikumar 

    Would you share USB traffic? to check whether it's timing issue or bandwidth limitation.

    Visitor II
    July 18, 2025

    Hello , mr @FBL 
    iam also facing  same problem above explained.

    1. As requested, I’m sharing the USB UVC packet trace captured using Wireshark  .

    2. Below is a brief explanation of how I'm preparing and sending UVC packets:

    • Resolution: 640x480

    • Format: YUV2 (16 bits per pixel)

    • Frame size : UVC_MAX_FRAME_SIZE   (UVC_FRAME_WIDTH * UVC_FRAME_HEIGHT * 16U / 8U)

    • Max packet size : USBD_VIDEO_EPIN_HS_MPS    2044U 

    • Payload header: 2 bytes (0x02 ,0x00)

    Once all packets for a frame are sent, I reset packet_index and wait for the next frame (indicated by  usb_tx_complete = 1  ( which is poll from DCMI frame interrupt ) ).

    Logic :

    VOID video_write_payload(UX_DEVICE_CLASS_VIDEO_STREAM *stream)
    {
        static uint8_t payload_header[2] = {0x02U, 0x00U};
        uint8_t *Pcktdata;
        uint16_t PcktSze, PcktIdx;
        UCHAR *buffer;
        ULONG buffer_length;
        static uint32_t packet_index = 0;
        uint32_t packet_count =  UVC_MAX_FRAME_SIZE / (USBD_VIDEO_EPIN_HS_MPS - 2U);  //
        uint32_t packet_remainder = UVC_MAX_FRAME_SIZE % (USBD_VIDEO_EPIN_HS_MPS - 2U);
     
        /* Get payload buffer */
        ux_device_class_video_write_payload_get(stream, &buffer, &buffer_length);
     
        /* Check if streaming is active */
        if (uvc_state == UVC_PLAY_STATUS_STREAMING)
        {
         if (usb_tx_complete == 1)
         {
            if (packet_index < packet_count)
            {
               PcktIdx = packet_index;
                PcktSze = USBD_VIDEO_EPIN_HS_MPS;
                Pcktdata = Rx_B_Temp + packet_index * (USBD_VIDEO_EPIN_HS_MPS - 2U);
                packet_index++;
            }
            else if (packet_index == packet_count)
            {
                PcktIdx = packet_index;
                PcktSze = packet_remainder + 2U;
                Pcktdata = Rx_B_Temp + packet_index * (USBD_VIDEO_EPIN_HS_MPS - 2U);
                packet_index++;
            }
            else
            {
                usb_tx_complete = 0;
                packet_index = 0;
                PcktSze = 2; // Send only the header
            }
    }
     
            if (PcktSze > 2U)
            {
                if (PcktIdx == 0U)
                {
                    /* Toggle frame start flag for the first packet */
                    payload_header[1] ^= 0x01U;
                }
     
                /* Add header and copy video data into the transmission buffer */
                ux_utility_memory_copy(buffer, payload_header, sizeof(payload_header));
                ux_utility_memory_copy(buffer + 2U, Pcktdata, PcktSze - 2U);
     
                /* Commit the payload */
                ux_device_class_video_write_payload_commit(stream, PcktSze);
            }
            else
            {
    //            /* Send only the header for the final packet */
                ux_utility_memory_copy(buffer, payload_header, sizeof(payload_header));
                ux_device_class_video_write_payload_commit(stream, 2U);
            }
        }
        else if (uvc_state == UVC_PLAY_STATUS_READY)
        {
            /* Prepare an empty payload with just a header */
            payload_header[1] = 0x00; // Clear flags
            ux_utility_memory_copy(buffer, payload_header, sizeof(payload_header));
            ux_device_class_video_write_payload_commit(stream, sizeof(payload_header));
        }
    }

    please unzip and filter ( usb.src== "1.14.3" ) . for easy monitoring.
     
    thank you,
     
    Technical Moderator
    July 18, 2025

    Hi @saikumar 

    I tried to replicate your issue using your code, with reference board, U5G9 disco kit. The device cannot enumerate at all.