You are here

Error in example UVC_AN75779. | Cypress Semiconductor

Error in example UVC_AN75779.

Summary: 5 Replies, Latest post by oscargomezf_2018731 on 01 Dec 2016 08:06 AM PST
Verified Answers: 0
Last post
Log in to post new comments.
oscargomezf_2018731's picture
User
15 posts

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.
nisa's picture
Cypress Employee
85 posts

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);

    CyU3PGpifGetSMState(0);

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

 

    return 0;

}

 

oscargomezf_2018731's picture
User
15 posts

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.

 

 

nisa's picture
Cypress Employee
85 posts

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

Attachments: 
oscargomezf_2018731's picture
User
15 posts

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.

oscargomezf_2018731's picture
User
15 posts

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.

Log in to post new comments.