cancel
Showing results for 
Search instead for 
Did you mean: 

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

saikumar
Senior

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!

4 REPLIES 4
FBL
ST Employee

Hi @saikumar 

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

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


saib
Associate II

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,
 
FBL
ST Employee

Hi @saikumar 

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

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Hello, mr @FBL 

Thank you for your reply and for trying to reproduce the issue.

By default, the U5G9 Discovery Kit provides a 16 MHz  clock to the USB HS PHY. However, in my setup, I'm using  external oscillator to provide 32MHz clock to the USB PHY.

Due to this hardware difference, I had to modify one parameter in the usb_otg.c file, specifically in  HAL_PCD_MspInit()  function, 

SYSCFG_OTG_HS_PHY_CLK_SELECT_1 (for 16Mhz)   to  SYSCFG_OTG_HS_PHY_CLK_SELECT_6  (for 32Mhz) 
so please  set it for 16Mhz as shown bellow

HAL_SYSCFG_SetOTGPHYReferenceClockSelection(SYSCFG_OTG_HS_PHY_CLK_SELECT_1);

 

Thanks,