Error in example UVC_AN75779.

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

cross mob
Anonymous
Not applicable

I'm using the MT9D131 OnSemiconductor camera with the UVC_AN75779 example, and it's working fine.

   

But I think I've found and error in a certain mode of operation. I'm working on Linux platform and I'm using v4l2-gtl to get frames. The error happens when I only get 1 frame:

   

v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=frame.yuv --stream-count=1

   

And I get this error:

   

streamingStarted == CyFalse -> Clear feature request detected..
Error in CyU3PDmaMultiChannelCommitBuffer: code 71
SUSPEND encountered...

   

But I've realised, that If I take a new image works fine without an error

   

streamingStarted == CyTrue -> Clear feature request detected..
Clear feature request detected.
SUSPEND encountered...

   

When I take an image the first time I haven't got any error so the odd captures work fine but the even captures I don't know why I've got this error:

   

streamingStarted == CyFalse -> Clear feature request detected..
Error in CyU3PDmaMultiChannelCommitBuffer: code 71
SUSPEND encountered...

   
    Can anyone help me to solve this problem?   
   
        
   
    Best regards.   
0 Likes
6 Replies
Anonymous
Not applicable

I suppose you are talking about the error code 0x71 which correcponds to CY_U3P_ERROR_INVALID_SEQUENCE

   

Generally this error comes when the host is not reading the data fast enough. In such a scenario, all the DMA buffers may get filled. As a result it causes a buffer overflow scenario on the GPIF side. This, in turn is causing the GetBuffer() API to return successfully even though there never was a new buffer available. Consequently, the CommitBuffer() goes on to commit a buffer that does not actually exist and hence throws this invalid sequence error.

   

The best way to avoid it would be to make sure that the host has enough bandwidth and is always ready to read the data as and when the device has it ready. Increasing the buffering within the FX3 would also help alleviate the issue.

   

Recovering from this would entail having to resume streaming from the next frame onwards. Until you come across this scenario again. This will result in lost data (and hence dropped frames) from time to time. You need to set a flag when you get this error (or better when you get a commit failure followed by this error). In the main thread for (;;), you need to check the status of this bit, and reset the communication if the failure is detected using a function which has the following sequence of events. And then clear the error/flag bit

   

uint8_t CyW_R()

   

{

   

                CyU3PGpifSMControl(CyTrue);

   

    /* Update the flag so that the application thread is notified of this. */

   

  //  glIsApplnActive = CyFalse;

   

 

   

    CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyTrue);

   

    CyU3PBusyWait (100);

   

 

   

    /* Abort and destroy the video streaming channel */

   

    /* Reset the channel: Set to DSCR chain starting point in PORD/CONS SCKT; set DSCR_SIZE field in DSCR memory*/

   

    CyU3PDmaMultiChannelReset(&glChHandleUVCStream);

   

    CyU3PThreadSleep(25);

   

 

   

    /* Flush the endpoint memory */

   

    CyU3PUsbFlushEp(CY_FX_EP_BULK_VIDEO);

   

    CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyFalse);

   

    CyU3PBusyWait (200);

   

 

   

      /* Enable USB 3.0 LPM */

   

    CyU3PUsbLPMEnable ();

   

                CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyTrue);

   

    CyU3PBusyWait (100);

   

    /* Reset USB EP and DMA */

   

    CyU3PUsbFlushEp(CY_FX_EP_BULK_VIDEO);

   

    status = CyU3PDmaMultiChannelReset (&glChHandleUVCStream);

   

    if (status != CY_U3P_SUCCESS)

   

    {

   

        CyU3PDebugPrint (4,"\n\rAplnStrt:ChannelReset Err = 0x%x", status);

   

        return status;

   

    }

   

    status = CyU3PDmaMultiChannelSetXfer (&glChHandleUVCStream, 0, 0);

   

    if (status != CY_U3P_SUCCESS)

   

    {

   

        CyU3PDebugPrint (4, "\n\rAplnStrt:SetXfer Err = 0x%x", status);

   

        return status;

   

    }

   

    CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyFalse);

   

    CyU3PBusyWait (200);

   

    /* Resume the Fixed Function GPIF State machine */

   

    CyU3PGpifSMControl(CyFalse);

   

 

   

   // glActiveSocket = 0;

   

    CyU3PGpifSMSwitch(257,0,257, 0, 2 );

   

    CyU3PThreadSleep (10);

   

    

   

   // CyU3PDebugPrint (4, "\n\rAplnStrt:SMState = 0x%x",SMState);

   

 

   

    return 0;

   

}

0 Likes
Anonymous
Not applicable

Hi Nishant,

   

Thank you in advance for your prompt reply.

   

Yes, I'm talking about the ERROR with code 71 (decimal value): CY_U3P_ERROR_INVALID_SEQUENCE.

   

I'm trying to understand well which you answer me. When you said: "This, in turn is causing the GetBuffer() API to return successfully even though there never was a new buffer available. Consequently, the CommitBuffer() goes on to commit a buffer that does not actually exist and hence throws this invalid sequence error."

   

1º.- I don't understand, you said that if the host isn't read the data fast enough, all DMA buffers may get filled, so the Get Buffer() API will have a buffer available but this buffer doesn't contain the correct data because was overwrite or if in the GPIF module occurs an overflow everything crash? If the GPIF module continues working fine we will lose some data but the application will have to continue working fine, won't we?

   

2º.- One of the recommendations to make sure that the host has enough bandwidth is increasing the buffering with the FX3. I found this code in the uvc.c:

   

...

   

    /* Create a DMA Manual channel for sending the video data to the USB host. */
    dmaMultiConfig.size           = CY_FX_UVC_STREAM_BUF_SIZE;
    dmaMultiConfig.count          = CY_FX_UVC_STREAM_BUF_COUNT;

   

    dmaMultiConfig.validSckCount  = 2;
    dmaMultiConfig.prodSckId [0]  = (CyU3PDmaSocketId_t)CY_U3P_PIB_SOCKET_0;
    dmaMultiConfig.prodSckId [1]  = (CyU3PDmaSocketId_t)CY_U3P_PIB_SOCKET_1;
    dmaMultiConfig.consSckId [0]  = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_CONS_0 | CY_FX_EP_VIDEO_CONS_SOCKET);
    dmaMultiConfig.prodAvailCount = 0;
    dmaMultiConfig.prodHeader     = 12;                 /* 12 byte UVC header to be added. */
    dmaMultiConfig.prodFooter     = 4;                  /* 4 byte footer to compensate for the 12 byte header. */
    dmaMultiConfig.consHeader     = 0

   

...

   

The values of the variables CY_FX_UVC_STREAM_BUF_SIZE and CY_FX_UVC_STREAM_BUF_COUNT are:

   

CY_FX_UVC_STREAM_BUF_SIZE = 0x400

   

CY_FX_UVC_STREAM_BUF_COUNT= 4

   

for example, increasing this values to 0x800 and 8 respectively, Would it be a good idea? But where can I modify this defines CY_FX_UVC_STREAM_BUF_SIZE and CY_FX_UVC_STREAM_BUF_COUNT?

   

 

   

Best regards.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

There is not overwrite of DMA buffers. Unless the data in the buffer is read, next data will not be stored in the buffer. 

   

CY_FX_UVC_STREAM_BUF_SIZE = 0x400 (1024 is very small).  We have used BUF_SIZE= 0x4000 in AN75779

   

​Please find the attached document which states how to increase the buffer size from 16KB to 32KB for this application. You can increase the count as per the available memory just by changing this macro CY_FX_UVC_STREAM_BUF_COUNT. CyUSB3014 has 224 KB of buffer area, so you may have to reduce the count further. You can try for yourself and see

0 Likes
Anonymous
Not applicable

Hi Nishant,

   

I was wrong I'm using the same example than you, so the variable CY_FX_UVC_STREAM_BUF_SIZE = (0x10) * (0x400). I dind't see the value 0x10. I'm sorry.

   

1º.- First of all, I would like to solve the problem of a possible error before to increase the buffer size. I want to avoid a stuck situation. For test the error CY_U3P_ERROR_INVALID_SEQUENCE and to try to get this error more frequently Can I reduce the CY_FX_UVC_STREAM_BUF_COUNT = 1 ? I think that in this way the host wasn't fast enough to read the data more frencuently was it?

   

 

   

Then when I have solved this problem I'm going to try to increase the buffer size from 16KB to 32KB.

   

Best regards.

0 Likes
Anonymous
Not applicable

Hi Nishant,

   

I think I've just got the mode to ignored the CY_U3P_ERROR_INVALID_SEQUENCE error and continue with the streaming video without broke the USB link. I've based the solution on your proposal, but with some modifications:

   

CyU3PReturnStatus_t CyFxUvcApplnRestart()
{
    CyU3PReturnStatus_t apiRetStatus;

   

    /* Disable the GPIF state machine. */
    CyU3PGpifDisable (CyFalse);

   

    /* Abort and destroy the video streaming channel */
    /* Reset the channel: Set to DSCR chain starting point in PORD/CONS SCKT; set DSCR_SIZE field in DSCR memory*/
    CyU3PDmaMultiChannelReset(&glChHandleUVCStream);
    CyU3PThreadSleep(25);

   

    /* Flush the endpoint memory */
    CyU3PUsbFlushEp(CY_FX_EP_BULK_VIDEO);

   

    apiRetStatus = CyU3PDmaMultiChannelReset (&glChHandleUVCStream);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4,"\n\rAplnStrt:ChannelReset Err = 0x%x", apiRetStatus);
        return apiRetStatus;
    }

   

    apiRetStatus = CyU3PDmaMultiChannelSetXfer (&glChHandleUVCStream, 0, 0);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        /* Error handling */
        CyU3PDebugPrint (4, "DMA Channel Set Transfer Failed, Error Code = %d\r\n", apiRetStatus);
        CyFxAppErrorHandler (apiRetStatus);
    }

   

    /* Start with frame ID 0. */
    glUVCHeader[1] &= ~CY_FX_UVC_HEADER_FRAME_ID;

   

    /* Start the state machine from the designated start state. */
    apiRetStatus = CyU3PGpifSMStart (START_SCK0, ALPHA_START_SCK0);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        /* Error Handling */
        CyU3PDebugPrint (4, "Starting GPIF state machine failed, Error Code = %d\r\n", apiRetStatus);
        CyFxAppErrorHandler (apiRetStatus);
    }

   

    return 0;
}

   

I had to avoid the functions: CyU3PUsbSetEpNak because they close the USB connection and I need to request streaming video from the host again. In this way, I only lost some frames but the connection remains working fine.

   

Could you check  that I haven't forgotten anything important and the function is OK? Pherhaps I need some CyU3PThreadSleep, I'm not a master in USB and UVC.

   

I have had an application running for 2 hours and I've got hundreds of errors: CY_U3P_ERROR_INVALID_SEQUENCE, but the streaming doesn't cut. I'm going to leave the application working all night.

   

I had to put the variable to CY_FX_UVC_STREAM_BUF_COUNT = 1 to get more errors, now I can change it again.

   

 

   

Best regards.

0 Likes
Anonymous
Not applicable

hi Nishant,

   

   Do you have the project of GPIF II and source code which was mentioned in your documentation.Please e-mail me a copy(396998850@qq.com),thanks.

0 Likes