Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

USB superspeed peripherals Forum Discussions

rossi
Level 3
Level 3
25 sign-ins First solution authored 10 replies posted

I'm writing USB 2.0 OTG UVC host firmware on FX3 and usb 2.0 web cam is used as device. 

The traffics generated between PC and web cam were captured by the Lecroy USB analyzer. (attached "pc_captured.usb")

I mimicked the traffics captured above in my UVC host firmware and those were captured in "fw_captured.usb"

The following shows the traffics around the time when SET_INTERFACE (Transfer 168) is called.

Unfortunately, after the 12 bytes of isochronous data from the web cam (Transfer 169), no more data from the device could be found.

"fw_captured.usb"

rossi_0-1664957038663.png

 

The following picture shows the traffic captured between PC and web cam.

Definitely we can clearly see data is coming continuously. (Transfer 202)

"pc_captured.usb"

rossi_0-1664958766397.png

 

 

Some relevant code snippets used in my host fimware are shown below,

UvcRecvThread is designed to receive data from web cam.

 

 

 

 

 

void UvcRecvThread( uint32_t Value) {
	uint8_t buffer[1024*4];
	uint16_t count = 1024;
	...

	for (;;)
	{
        buf_p.buffer = buffer;
        buf_p.count  = 0;
        buf_p.size   = ((count + 0x0F) & ~0x0F);
        buf_p.status = 0;

        status = CyU3PDmaChannelSetupRecvBuffer (&glHostUvcCh, &buf_p);
        status = CyU3PUsbHostEpSetXfer (glHostUvcEp,CY_U3P_USB_HOST_EPXFER_NORMAL, count);
        status = CyU3PUsbHostEpWaitForCompletion (glHostUvcEp, &epStatus, CYU3P_WAIT_FOREVER);
        status = CyU3PDmaChannelWaitForCompletion (&glHostUvcCh, CYU3P_NO_WAIT);
        status = CyU3PDmaChannelGetStatus (&glHostUvcCh, &state, &prodXferCount, &consXferCount);
	}
}

 

 

 

 

 

 

End point and DMA channel setup were done as below

 

 

 

 

 

   /* Initialize the UVC */
    CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg));
    epCfg.type = CY_U3P_USB_EP_ISO;
    epCfg.mult = 1;
    epCfg.maxPktSize = size;
    epCfg.pollingRate = 0;
    size = ((size + 0x0F) & ~0x0F);
    epCfg.fullPktSize = size;
    epCfg.isStreamMode = CyFalse;
    status = CyU3PUsbHostEpAdd (glHostUvcEp, &epCfg);

    /* Create a DMA channel for this EP. */
    CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));
    dmaCfg.size = size;
    dmaCfg.count = 0;
    dmaCfg.prodSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_PROD_0 + (0x0F & glHostUvcEp));
    dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;
    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
    dmaCfg.notification = 0;
    dmaCfg.cb = NULL;
    dmaCfg.prodHeader = 0;
    dmaCfg.prodFooter = 0;
    dmaCfg.consHeader = 0;
    dmaCfg.prodAvailCount = 0;
    status = CyU3PDmaChannelCreate (&glHostUvcCh, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg);

 

 

 

 

 

 

Why I couldn't receive more data after receiving 12 bytes of data from web cam?

 

Regards,

Rossi

0 Likes
1 Solution
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Rossi,

Thank you. Glad to hear that the comments were helpful.

- The data transfer is blocked after 1~3 seconds in CyU3PUsbHostEpWaitForCompletion again.

>> Please try setting the timeout value to 1s or 3s   for this CyU3PUsbHostEpWaitForCompletion API. It looks like as the host is expecting 1024 bytes and device only sent 908 bytes the control is stuck in CyU3PUsbHostEpWaitForCompletion. So, we can put a timeout value and then check epStatus to understand the cause of failure. If it's a timeout error, you can continue to schedule the new 1024 byte request

When isochronous transfer occurs, those transactions had to be grouped in one transfer within my understanding but the result is not.

>> This is because the Host (Fx3) is requesting 1024 bytes in one transfer (CyU3PUsbHostEpSetXfer). You can try reading 2K data instead of 1K and check if the two transfers are grouped to one

From the traces, I see that 10KB + 908 bytes of data is received. Please let me know if every time the same amount of data is received by FX3

 

Regards,
Rashi

View solution in original post

0 Likes
9 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

Please confirm that the endpoint parameters are set based on the endpoint descriptors reported by the device.

For example, polling rate (bytes/ interval), mult, size, etc. 

We recommend to setup the endpoint based on the descriptors reported by device. 

Please call the APIs only when the previous API is success and let me know if there are any failures or is the issue still the same.

Also, the pc_captured trace seems to be truncated, an you please provide the complete trace to evaluate

Regards,
Rashi
0 Likes

Okay, I'll investigate in more detail about the endpoint parameters.

About the API calls, you're absolutely right. That is just temporary experimental one. In my next test, it will be changed accordingly.

Full pc_captured trace can be found in attached "captured.zip".

I'll be back with my new test results.

Regards,

Rossi

0 Likes

I tested as your recommendations, but still I'm facing the same problem. In below I described how I did.

The retrieved endpoint information of my web cam. (interefaceNumber=1, AlternateSetting=6)

ep.png

With this in mind, I changed the epCfg as follows (Not sure if I'm right)

 

 

    size = 1024;
    /* Initialize the UVC */
    CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg));
    epCfg.type = CY_U3P_USB_EP_ISO;
    epCfg.mult = 2;
    epCfg.maxPktSize = size;
    epCfg.pollingRate = 1;
    size = ((size + 0x0F) & ~0x0F);
    epCfg.fullPktSize = size;
    epCfg.isStreamMode = CyFalse;
    status = CyU3PUsbHostEpAdd (glHostUvcEp, &epCfg);

 

 

 

DMA Channel setup was not changed.

 

UvcRecvThread was modified as below.

 

 

void
UvcRecvThread(
		uint32_t Value)
{
    ...
	CyU3PDebugPrint(4,"UvcRecvThread starts\r\n");
	for (;;)
	{
        buf_p.buffer = buffer;
        buf_p.count  = 0;
        buf_p.size   = ((count + 0x0F) & ~0x0F);
        buf_p.status = 0;

        CyU3PDebugPrint(4,"CyU3PDmaChannelSetupRecvBuffer...\r\n");
        status = CyU3PDmaChannelSetupRecvBuffer (&glHostUvcCh, &buf_p);
        CyU3PDebugPrint(4,"CyU3PDmaChannelSetupRecvBuffer status=0x%x,size=%d\r\n",status,buf_p.size);
        if(status!=CY_U3P_SUCCESS) continue;

        CyU3PDebugPrint(4,"CyU3PUsbHostEpSetXfer(%d)...\r\n",count);
        status = CyU3PUsbHostEpSetXfer (glHostUvcEp,CY_U3P_USB_HOST_EPXFER_NORMAL, count);
        CyU3PDebugPrint(4,"CyU3PUsbHostEpSetXfer status=0x%x,count=%d\r\n",status,count);
        if(status!=CY_U3P_SUCCESS) continue;

        CyU3PDebugPrint(4,"CyU3PUsbHostEpWaitForCompletion...\r\n");
        status = CyU3PUsbHostEpWaitForCompletion (glHostUvcEp, &epStatus, CYU3P_WAIT_FOREVER);
        CyU3PDebugPrint(4,"CyU3PUsbHostEpWaitForCompletion status=0x%x,ep=0x%x,epStatus=0x%x\r\n",status,glHostUvcEp,epStatus);
        if(status!=CY_U3P_SUCCESS) continue;

        CyU3PDebugPrint(4,"CyU3PDmaChannelWaitForCompletion...\r\n");
        status = CyU3PDmaChannelWaitForCompletion (&glHostUvcCh, CYU3P_NO_WAIT);
        CyU3PDebugPrint(4,"CyU3PDmaChannelWaitForCompletion status=0x%x\r\n",status);
        if(status!=CY_U3P_SUCCESS) continue;

        status = CyU3PDmaChannelGetStatus (&glHostUvcCh, &state, &prodXferCount, &consXferCount);
        CyU3PDebugPrint (4,"CyU3PDmaChannelGetStatus status=0x%x state=0x%x length=%d\r\n",status,state,prodXferCount);
	}
}

 

 

 

UART debugging log for the above

 

 

UvcRecvThread starts
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...

 

 

 

The UvcRecvThread is blocked at CyU3PUsbHostEpWaitForCompletion call.

 

USB Traffic(see attached file, 20221006_test_1.zip) captured for this test, still after 12 bytes (Transfer 172), no more data found

rossi_0-1665024104462.png

 

I'm not sure the EP parameters that I used were suitable. I have no idea what is wrong yet.

 

Regards,

Rossi

0 Likes
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Rossi,

Thank you for the details.

From the traces shared earlier and shared in your previous post, it looks like that you are calling SetupRecvBuffer even before the device has enumerated.

Please make sure that data transfers start after the SET_INTERFACE request is responded by the device. Also, in the trace, I do not see the device address set after the SET_CONFIGURATION request is sent by the FX3 (host). Kindly, set a new address for the device (as done by PC) when SET_CONFIGURATION is done.

In the pc_captured trace, I see that the device (USB cam) sends only 12 bytes every time i.e. only the UVC header. Is the host application on the PC modified to receive only the UVC header. If yes, please  try requesting 12 bytes from the device when CyU3PUsbHostEpSetXfer API is called.

pc_capture_12B.PNG

Please try the following endpoint configuration

size = 1024;
    /* Initialize the UVC */
    CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg));
    epCfg.type = CY_U3P_USB_EP_ISO;
    epCfg.mult = 3;
    epCfg.maxPktSize = size;
    epCfg.pollingRate = 0;
    size = ((size + 0x0F) & ~0x0F);
    epCfg.fullPktSize = size;
    epCfg.isStreamMode = CyFalse;
    status = CyU3PUsbHostEpAdd (glHostUvcEp, &epCfg);

Off the topic, wanted to let you know that errata 4 of the FX3 data is applicable for FX3 as an embedded host as well. To avoid the issue mentioned in the errata, we would suggest configuring the endpoint with a lower "mult" value. 

Please let me know if the mult value of the USB camera (device )can be changed to debug the problem

Regards,
Rashi
0 Likes

Thank you for your reply, Rashi

 

1.

The pc_captured trace was done in the following environemnt.

i.e.,        [VLC player in PC(Windows10)]  < --usb connection->  Webcam

So, the trace is reliable & correct one. If you scroll down further more, you would see some real data transfers like the following, 

rossi_0-1665042528303.png

 

2. Your recommendation that I call SetupRecvBuffer before the device is enumerated seems quite reasonable.

After I changed epCfg as your suggestions (mult=3, pollingRate=0), I added sleep before the for loop like, 

 

 

 

 

void
UvcRecvThread(
		uint32_t Value)
{
...
	CyU3PThreadSleep (3000);
	CyU3PDebugPrint(4,"UvcRecvThread starts\r\n");
	for (;;)
	{
...
        }
}

 

 

 

 

 

Then my firmware could receive data from the device. The logs are as follows.

 

 

 

 

UvcRecvThread starts
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x1
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x1
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x1
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x0
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...

 

 

 

 

 

Surely it starts to receive data finally. However, after 1~3 seconds later, the firmare blocked again in CyU3PUsbHostEpWaitForCompletion. For now, at lease we solved one issue but seems like there are more.

 

When I look at the pc_captured trace(the correct trace as I mentioned above), it looks like this. All isochronous traffics are grouped as one transfer(Transfer202) which is the typical style in isochronous transfer.

rossi_1-1665043318382.png

 

However unlike in pc_captured trace, in my case, the trace is not what I expected, Those isochronous transfers are not grouped in one transfer but splitted in many different transfers (Transfer 171,172,...180)

rossi_2-1665043491134.png

 

For now, seems like there are 2 issues.

- The data transfer is blocked after 1~3 seconds in CyU3PUsbHostEpWaitForCompletion again.

- When isochronous transfer occurs, those transactions had to be grouped in one transfer within my understanding but the result is not.

(The tested trace is attached, ""experiment1.usb")

 

Deep appreciation on your comments.

Regards,

Rossi

0 Likes
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Rossi,

Thank you. Glad to hear that the comments were helpful.

- The data transfer is blocked after 1~3 seconds in CyU3PUsbHostEpWaitForCompletion again.

>> Please try setting the timeout value to 1s or 3s   for this CyU3PUsbHostEpWaitForCompletion API. It looks like as the host is expecting 1024 bytes and device only sent 908 bytes the control is stuck in CyU3PUsbHostEpWaitForCompletion. So, we can put a timeout value and then check epStatus to understand the cause of failure. If it's a timeout error, you can continue to schedule the new 1024 byte request

When isochronous transfer occurs, those transactions had to be grouped in one transfer within my understanding but the result is not.

>> This is because the Host (Fx3) is requesting 1024 bytes in one transfer (CyU3PUsbHostEpSetXfer). You can try reading 2K data instead of 1K and check if the two transfers are grouped to one

From the traces, I see that 10KB + 908 bytes of data is received. Please let me know if every time the same amount of data is received by FX3

 

Regards,
Rashi
0 Likes

Hello Rashi

As you mentioned, after applying thread sleep before the loop of UvcRecvThread, initial blocking after 12 bytes of data is gone. 😀

The method you proposed this time seems little complicated so, I did the following simple test first. 

The ep setup is to use Bulk instead of Isochronous.

 

    /* Initialize the UVC */
    CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg));
    epCfg.type = CY_U3P_USB_EP_BULK;
    epCfg.mult = 1;
    epCfg.maxPktSize = size;
    epCfg.pollingRate = 1;
    size = ((size + 0x0F) & ~0x0F);
    epCfg.fullPktSize = size;
    epCfg.isStreamMode = CyFalse;
    status = CyU3PUsbHostEpAdd (glHostUvcEp, &epCfg);

 

 

The resulting logs are..

 

UvcRecvThread starts
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x1
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x0
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x0
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
CyU3PDmaChannelSetupRecvBuffer...
CyU3PDmaChannelSetupRecvBuffer status=0x0,size=1024
CyU3PUsbHostEpSetXfer(1024)...
CyU3PUsbHostEpSetXfer status=0x0,count=1024
CyU3PUsbHostEpWaitForCompletion...
CyU3PUsbHostEpWaitForCompletion status=0x0,ep=0x81,epStatus=0x0
CyU3PDmaChannelWaitForCompletion...
CyU3PDmaChannelWaitForCompletion status=0x0
CyU3PDmaChannelGetStatus status=0x0 state=0xB length=1024
....

 

 

Unlike the blocking that found on isochronous test, there was no such a blocking at all.

It worked pretty well.

 

I'm quite curios that the web cam definitely provides data in isochronous mode only, but I received in bulk mode. It doesn't seem quite reasonable for me. How should I interpret this test result?

 

Thanks always

Regards,

Rossi

 

p.s

During the test, my usb analyzer broke out some power issue. It seems like it'll take some time to get it fixed. Next tests will be available when it is ready.

0 Likes
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Rossi,

From this thread  Solved: STALL error found while receiving data from UVC ca... - Infineon Developer Community   it looks like the streaming through an isochronous endpoint works fine

Regards,
Rashi
0 Likes

Hello Rashi

The issue that I asked in this thread was solved. 

The details how I worked around the blocking are described in the thread you mentioned above (Solved: STALL error found while receiving data from UVC ca... - Infineon Developer Community )

Your comments (the one that I chose as a solution) were very helpful. According to our discussions, the following changes were made.

 

 

for(;;) {
    ...
    status = CyU3PUsbHostEpSetXfer (glHostUvcEp,CY_U3P_USB_HOST_EPXFER_NORMAL, count);
    if(status!=CY_U3P_SUCCESS) continue;

    /* CYU3P_WAIT_FOREVER blocks thread infinitely */
    //status = CyU3PUsbHostEpWaitForCompletion (glHostUvcEp, &epStatus, CYU3P_WAIT_FOREVER);

    /* there could be data waiting smaller than count! so apply timeout */
    status = CyU3PUsbHostEpWaitForCompletion (glHostUvcEp, &epStatus, 10);

    /* even though timeout(0x45) occurs, it doesn't mean transfer failure and in my investigation EP was ok, so I deleted this line
    */
    //if(status!=CY_U3P_SUCCESS) continue; 
    ...
}

 

 

 

Now the issue is cleared but during the test, another issue was found. I will create another thread on this issue later. 

 

Thank you

Regards,

Rossi

0 Likes