The DMA buffer size in cycx3_uvc_ov5640 firmware

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

cross mob
waka_297076
Level 1
Level 1

Hi,

   

    I have a question about the cycx3_uvc_ov5640 firmware in the SDK cx3_examples.

   

    When the firmware creates a DMA Manual OUT channel for streaming data,the DMA buffer size is set to 24KB,and the usb bulk endpoint transfer with burst is set to 16KB.

   

    I tried to modify the DMA buffer size(CX3_UVC_DATA_BUF_SIZE) to 0x3FF0(16KB) instead of 0x5FF0(24KB),the AMCAP can worked well in all the resolutions except 2592*1944.  And when setting the DMA buffer size to 0x6FF0,the AMCAP can not worked in any resolutions.  It's seems that only 0x5FF0 can worked well.

   

    Refer to AN75779 and AN90369, Is it right that I think the DMA buffer size should be equal to 16kB,in order to cpu could add 12 bytes uvc video data header for a maximum of 16 bursts of 1024 bytes over BULK Endpoints?

   

    Could anyone give me some advices about this question?

   

    Many thanks!

   

CX3RDKOV5640.h:

   

 /* UVC Buffer Parameters*/

   

#define ES_UVC_SS_DATA_BUF_SIZE (0x5FF0)        /* DMA Buffer Data Size Used: 12272 Bytes*/

   

#define ES_UVC_HS_DATA_BUF_SIZE (3056)         /* DMA Buffer Data Size Used: 3056 Bytes*/

   

 

   

#define ES_UVC_PROD_HEADER                     (12)            /* UVC DMA Buffer Header Size */

   

#define ES_UVC_PROD_FOOTER (4)             /* UVC DMA Buffer Footer Size */

   

 

   

/* UVC Buffer size - Will map to bulk Transaction size SuperSpeed*/

   

#define ES_UVC_SS_STREAM_BUF_SIZE (ES_UVC_SS_DATA_BUF_SIZE + ES_UVC_PROD_HEADER + ES_UVC_PROD_FOOTER)

   

 

   

/* UVC Buffer size - Will map to bulk Transaction size HighSpeed*/

   

#define ES_UVC_HS_STREAM_BUF_SIZE (ES_UVC_HS_DATA_BUF_SIZE + ES_UVC_PROD_HEADER + ES_UVC_PROD_FOOTER)

   

 

   

/* UVC Buffer count */

   

#define ES_UVC_SS_STREAM_BUF_COUNT              (4)

   

#define ES_UVC_HS_STREAM_BUF_COUNT (8)

   

 

   

CX3RDKOV5640.c:

   

 switch(CyU3PUsbGetSpeed())

   

    {

   

        case CY_U3P_HIGH_SPEED:

   

            endPointConfig.pcktSize = 0x200;

   

            endPointConfig.burstLen = 1;

   

            ES_UVC_STREAM_BUF_SIZE = ES_UVC_HS_STREAM_BUF_SIZE;

   

            ES_UVC_DATA_BUF_SIZE = ES_UVC_HS_DATA_BUF_SIZE;

   

            ES_UVC_STREAM_BUF_COUNT = ES_UVC_HS_STREAM_BUF_COUNT;

   

            break;

   

 

   

        case CY_U3P_FULL_SPEED:

   

            endPointConfig.pcktSize = 0x40;

   

            endPointConfig.burstLen = 1;

   

            break;

   

 

   

        case CY_U3P_SUPER_SPEED:

   

        default:

   

            endPointConfig.pcktSize = ES_UVC_EP_BULK_VIDEO_PKT_SIZE;  //16KB

   

            endPointConfig.burstLen = 16;

   

            ES_UVC_STREAM_BUF_SIZE = ES_UVC_SS_STREAM_BUF_SIZE;

   

            ES_UVC_DATA_BUF_SIZE = ES_UVC_SS_DATA_BUF_SIZE;

   

            ES_UVC_STREAM_BUF_COUNT = ES_UVC_SS_STREAM_BUF_COUNT;

   

            break;

   

    }

   

 

   

    status = CyU3PSetEpConfig(ES_UVC_EP_BULK_VIDEO, &endPointConfig);

   

    if (status != CY_U3P_SUCCESS)

   

    {

   

        CyU3PDebugPrint (4, "\n\rAppInit:CyU3PSetEpConfig BulkEp Err = 0x%x", status);

   

        esUVCAppErrorHandler(status);

   

    }

   

 

   

    CyU3PUsbEPSetBurstMode (ES_UVC_EP_BULK_VIDEO, CyTrue);

   

 

   

    /* Flush the endpoint memory */

   

    CyU3PUsbFlushEp(ES_UVC_EP_BULK_VIDEO);

   

 

   

    /* Create a DMA Manual OUT channel for streaming data */

   

    /* Video streaming Channel is not active till a stream request is received */

   

    dmaCfg.size                 = ES_UVC_STREAM_BUF_SIZE; //24KB

   

    dmaCfg.count                = ES_UVC_STREAM_BUF_COUNT; //4 buffer

   

    dmaCfg.validSckCount        = 2;

   

 

   

    dmaCfg.prodSckId[0]         = ES_UVC_PRODUCER_PPORT_SOCKET_0;

   

    dmaCfg.prodSckId[1]         = ES_UVC_PRODUCER_PPORT_SOCKET_1;

   

 

   

    dmaCfg.consSckId[0]         = ES_UVC_EP_VIDEO_CONS_SOCKET;

   

    dmaCfg.dmaMode              = CY_U3P_DMA_MODE_BYTE;

   

    dmaCfg.notification         = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

   

    dmaCfg.cb                   = esUVCUvcAppDmaCallback;

   

    dmaCfg.prodHeader           = ES_UVC_PROD_HEADER;

   

    dmaCfg.prodFooter           = ES_UVC_PROD_FOOTER;

   

    dmaCfg.consHeader           = 0;

   

    dmaCfg.prodAvailCount       = 0;

   

 

   

    status = CyU3PDmaMultiChannelCreate (&glChHandleUVCStream, CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE , &dmaCfg);

0 Likes
2 Replies
Anonymous
Not applicable

In a general note, there are a few things you need to check before changing the buffer size:

   

 

   

1. the frame should end in a partial buffer: This is because we use this to set the EOF bit and toggle the frame ID. And a partial buffer is guaranteed if total_frame_size_in_bytes/(dma_buf_size - header - footer) is not an integer.

   

 

   

2. the DMA buffer size must be a multiple of the GPIF bus size. So for a 24-bit bus, the buffer size has to be a multiple of 3 (as 3 bytes are read in one cycle) and so on. In CX3, this is specified as the first parameter to CyU3PMipicsiGpifLoad().

   

 

   

And when you change the buffer size, make sure that the maximum declared UVC payload size is more than the new buffer size. The payload size is a 4-byte field in the probe control structure (typically glProbeCtrl[]).

   

 

   

In your case, 2592*1944 with 16KB buffer size should result in a partial buffer (2592*1944*2/(16*1024-16) == 615.69) and is a multiple of 2 (assuming YUV422; 16-bit). So, if you don't see video on the PC, you may be sending less data than one frame. Print out the number of full buffers that you've sent in that frame and verify that it's 615 (or 616 depending on how you count).

   

 

   

Alternatively, the DMA channel is probably being reset too often. Check if the handler for CX3_DMA_RESET_EVENT is being called. If it is, it could be from a failed CommitBuffer() call in the DMA callback.

0 Likes
waka_297076
Level 1
Level 1

Hi scutifer,

   

Thank you for your support!

   

I use ov5640 header board,and with the Cypress cx3_uvc_ov5640 firmware,Amcap can work well in VGA,720P,1080P and 2592*1944 .It  seems that CyCx3GpifCB() warp up the partial buffer. But when I modify the DMA buffer size to 16KB instead of 24KB,Amcap can works in all resolutions except 2592*1944.

   

Cypress note AN75779 mentioned that the UVC spec requires adding a 12-byte header to each USB transfer (meaning each 16-KB DMA buffer).

   

In the OV5640 firmware,the bulk endpoint is configure to 16kB,and the dma buffer size is configure to 24KB.

   

If the USB Endpoint read 16KB from the dma buffer for each burst transfer ,how to handled the extra 8KB datas of the dma buffer?

   

Please give me some suggests,Thanks you!

0 Likes