cancel
Showing results for 
Search instead for 
Did you mean: 

USB Superspeed Peripherals

haxu_299926
New Contributor

I want to receive the date ,and first send a leader package, then a data package, and then a trailer package as the end. Similar to UVC header, but UVC header is not an independent buffer,I need the leader and trailer an  independent buffer.How can I implement this operation?How to get an empty dmabuffer,use the getbuffer api?

0 Likes
1 Solution
Rashi_Vatsa
Moderator
Moderator

Hello,

Please refer to the GPIF to USB example attached.

I have made certain changes to the default firmware. I am using CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE in override mode.

I have checked this firmware at my end. I am able to get the random values sent through the API CyU3PDmaMultiChannelSetupSendBuffer .(Refer Attachment)

As per your previous response. Error 0x42 - CY_U3P_ERROR_NOT_STARTED

I went through the source code CyU3PDmaMultiChannelSetXfer and CyU3PDmaMultiChannelReset do not check or return CY_U3P_ERROR_NOT_STARTED . There is some other API which is causing this error. Please confirm this.

I am not able to test the results using your firmware (due to host application constraints) .Please refer to GPIF to USB firmware and make similar changes to your firmware.

Regards,

Rashi

Regards,
Rashi

View solution in original post

0 Likes
19 Replies
Rashi_Vatsa
Moderator
Moderator

Hello,

Please let me know the size of the leader and trailer data.

Why do you need an independent buffer for that?

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hi,Rashi,

the size of the leader is 52bytes and the trailer is 32bytes,I want to send the leader and trailer independent,not to send the buffer contains the leader and the valid image datas.

leader packet

data packt

...

date packet

trailer packet

In the example of cycx3_uvc_ov5640, the CyCx3UvcAppDmaCallback function,when the type equal CY_U3P_DMA_CB_PROD_EVENT,it getbuffer and add the UVC header ,and then commit the buffer to consumer. it always in use of the same buffer.

I want to send the leader packet when the frame start and send the trailer packet when the frame end, but I can't modify the GPIF statemachine,so I can't catch the point of the frame start. for that, I think whether I can send the leader packet when I received the first image date  buffer in the  CyCx3UvcAppDmaCallback function ,but I don't have the empty buffer.and how to get a new buffer,to use getbuffer?and then use the commitbuffer to send?

I don't know whether you understand my problem,and do you have some good suggestions?

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

I understand.

As the DMA channel is created between the GPIF  (producer) and the USB (consumer) block. The modifications to the DMA buffer can be done in the DMA call back. Independent buffer cannot be added to the DMA buffers from the DMA callback.

There are some possibilities when you want to add leader and trailer buffer:

- The USB 3.0 will allow endpoint size as 16 x 1024 bytes. So when you will send only 52 bytes (leader buffer), it would be committed as a short packet. So in that micro frame instead of 16KB only 52 bytes will be sent. This will reduce the data throughput of your application.

- If you can have FPGA between the Camera and CX3, then you can add these trailer and leader within FPGA and stream the data through CX3.

- There is an option to configure the DMA channel in the overriding mode but it would be quite  complex. You can go through the API supporting this mode from the FX3APIguide. Please let me know if any queries on that.

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hi,Rashi,

I don't want to use the FPGA between the Camera and CX3,because the reason I chose the cx3 is to reduce costs.

and I can't reduce the data throughput of your application,so the method 1 and 2 seems to be Infeasible.

I have read the FX3APIguide,but I still don't know  how to configure the DMA channel in the overriding mode, Can you give me an example?

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

If you wan to go for DMA channel override mode, there will be reduction in data throughput.

As the leader is having 52 bytes and the total buffer size would be 16 KB, hence there would be a short packet committed to the host. This would effect the data throughput as you will be sending only 52 bytes instead of 16 KB in one micro fframe

If you don't want to change the data throughput, I would suggest to send the leader and trailer along with the Frame data and then filter it out in the host application.

Please let me know if you still go for DMA Override mode.

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hi,Rashi,

      I can't accept reduce the data throughput,Can I modify the gpif of the cx3?Can I create a new DMA channel for sending header and trailer packets?

      Can I use the CyU3PDmaMultiChannelSetupSendBuffer,send the header packet?

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

- CyU3PDmaMultiChannelSetupSendBuffer API is used when DMA channel is in Override mode. The description of this API mentions it in FX3APIGuide.

-Creating a DMA channel for sending the header and trailer is possible. But the endpoints used would be different. The host application should be programmed such that it would take the data from different endpoints. Synchronization of the Leader /Trailer need to be done with original data. This would need lot of changes.

- CX3 has fixed GPIF state machine. I will let you know if we could help you on this.

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

                        

Hi,Rashi,

     It seems that Creating a DMA channel for sending the header and trailer is Unworkable.Do you have another method to solve this problem? How do I know frame start,and first send the leader packet and then send the data packet

0 Likes
haxu_299926
New Contributor

Hi,Rashi,

       Can I change the DMA channel of the stream to MANUAL IN and MANUAL OUT MODE,I try to modify this ,but I found the function CyU3PDmaChannelCreate return error,the error code is ERROR_BAD_ARGUMENT

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

Can you share the snapshot of the DMA channel configuration that you are passing to CyU3PDmaChannelCreate function?

For example:

         dmaCfg.size  =32768;

           dmaCfg.count = 2;

           dmaCfg.prodSckId = CY_FX_PRODUCER_USB_SOCKET;

           dmaCfg.consSckId =CY_U3P_CPU_SOCKET_CONS ;

           dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

           // Enabling the callback for produce event.

           dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;

          dmaCfg.cb =CyFxBulkSrcSinkDmaCallback1;

           dmaCfg.prodHeader = 0;

           dmaCfg.prodFooter = 0;

           dmaCfg.consHeader = 0;

           dmaCfg.prodAvailCount = 0;

           apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,

           CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg);

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hi,Rashi,

        I change the DMA channel of the stream to MANUAL IN and MANUAL OUT MODE.

now I can create the dma channel successful,when I try to commit the dmabuffer to the consume, I can't catch the packet in the bushound,and then the second time get the buffer from the channel of glChHandleStreamOut,it will return the error of 0x45,the first time return is success.Can you tell me the problem of my code ,thank you very much!

the code is as follow:

In the function CyCx3UvcApplnInit:

     stInDmaCfg.size                 = CX3_UVC_STREAM_BUF_SIZE;

     stInDmaCfg.count                = CX3_UVC_STREAM_BUF_COUNT;

     stInDmaCfg.consHeader           = 0;

     stInDmaCfg.consSckId            = CY_U3P_CPU_SOCKET_CONS;

     stInDmaCfg.prodSckId            = CX3_PRODUCER_PPORT_SOCKET_1;

     stInDmaCfg.dmaMode              = CY_U3P_DMA_MODE_BYTE;

     stInDmaCfg.notification         = CY_U3P_DMA_CB_PROD_EVENT;

     stInDmaCfg.cb                   = CyCx3UvcAppDmaCallback;

     stInDmaCfg.prodHeader           = 0;

     stInDmaCfg.prodFooter           = 0;

     stInDmaCfg.consHeader           = 0;

     stInDmaCfg.prodAvailCount       = 0;

     status = CyU3PDmaChannelCreate (&glChHandleStreamIn,

    CY_U3P_DMA_TYPE_MANUAL_IN , &stInDmaCfg);

     if (status != CY_U3P_SUCCESS)

     {

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

     }

     CyU3PThreadSleep(100);

     stOutDmaCfg.size                 = CX3_UVC_STREAM_BUF_SIZE;

     stOutDmaCfg.count                = 1;

     stOutDmaCfg.consHeader           = 0;

     stOutDmaCfg.consSckId            = CY_U3P_UIB_SOCKET_CONS_1;

     stOutDmaCfg.prodSckId            = CY_U3P_CPU_SOCKET_PROD;

     stOutDmaCfg.dmaMode              = CY_U3P_DMA_MODE_BYTE;

     stOutDmaCfg.notification         = CY_U3P_DMA_CB_CONS_EVENT;

     stOutDmaCfg.cb                   = CyCx3UvcAppDmaCallback;

     stOutDmaCfg.prodHeader           = 0;

     stOutDmaCfg.prodFooter           = 0;

     stOutDmaCfg.consHeader           = 0;

     stOutDmaCfg.prodAvailCount       = 0;

     status = CyU3PDmaChannelCreate (&glChHandleStreamOut,

    CY_U3P_DMA_TYPE_MANUAL_OUT , &stOutDmaCfg);

     if (status != CY_U3P_SUCCESS)

     {

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

     }

     CyU3PThreadSleep(100);

/* DMA callback function to handle the produce and consume events. */

    void

CyCx3UvcAppDmaCallback (

        CyU3PDmaChannel   *chHandle,

        CyU3PDmaCbType_t  type,

        CyU3PDmaCBInput_t *input

        )

{

    CyU3PDmaBuffer_t DmaBuffer;

    CyU3PDmaBuffer_t DmaOutBuffer;

    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    CyU3PDebugPrint (4, "\n\CyCx3UvcAppDmaCallback:type  = 0x%x",type);

    if (type == CY_U3P_DMA_CB_PROD_EVENT)

    {

        /* This is a produce event notification to the CPU. This notification is

         * received upon reception of every buffer. The buffer will not be sent

         * out unless it is explicitly committed. The call shall fail if there

         * is a bus reset / usb disconnect or if there is any application error. */

        /* Disable USB 3.0 LPM while Buffer is being transmitted out*/

        if ((CyU3PUsbGetSpeed () == CY_U3P_SUPER_SPEED) && (doLpmDisable))

        {

            CyU3PUsbLPMDisable ();

            CyU3PUsbSetLinkPowerState (CyU3PUsbLPM_U0);

            CyU3PBusyWait (200);

            doLpmDisable = CyFalse;

#ifdef RESET_TIMER_ENABLE

            CyU3PTimerStart (&UvcTimer);

#endif

        }

        status = CyU3PDmaChannelGetBuffer(&glChHandleStreamIn, &DmaBuffer, CYU3P_WAIT_FOREVER);

        status = CyU3PDmaChannelGetBuffer(&glChHandleStreamOut, &DmaOutBuffer, CYU3P_NO_WAIT);

       // CyU3PDebugPrint (4, "\n\CyCx3UvcAppDmaCallback:status2  = 0x%x",status);

  //      while (status == CY_U3P_SUCCESS)

        {

     

  /* Commit Buffer to USB*/

  CyU3PMemCopy(DmaOutBuffer.buffer, DmaBuffer.buffer, DmaBuffer.count);

// status = CyU3PDmaChannelDiscardBuffer(&glChHandleStreamIn);

// if(status != CY_U3P_SUCCESS)

// {

// CyU3PDebugPrint(1,"\r\n CyU3PDmaChannelDiscardBuffer failed error = %x",status);

// //CyFxAppErrorHandler(stat);

// }

  status = CyU3PDmaChannelCommitBuffer (&glChHandleStreamOut, (DmaBuffer.count), 0);

      //   CyU3PDebugPrint (4, "\n\CyCx3UvcAppDmaCallback:status  = 0x%x,0x%x",status, *(uint8_t *)DmaOutBuffer.buffer);

  if (status != CY_U3P_SUCCESS)

  {

    CyU3PEventSet(&glCx3Event, CX3_DMA_RESET_EVENT,CYU3P_EVENT_OR);

  //   break;

  }

  else

  {

  glDMATxCount++;

  glDmaDone++;

  }

            }

          //  glActiveSocket ^= 1; /* Toggle the Active Socket */

         //   status = CyU3PDmaChannelGetBuffer(chHandle, &DmaBuffer, CYU3P_WAIT_FOREVER);

        }

    }

    else if(type == CY_U3P_DMA_CB_CONS_EVENT)

    {

    glDmaDone--;

        /* Check if Frame is completely transferred */

        glIsStreamingStarted = CyTrue;

        if((glHitFV == CyTrue) && (glDmaDone == 0))

        {

            glHitFV = CyFalse;

            glDMATxCount=0;

#ifdef RESET_TIMER_ENABLE

            CyU3PTimerStop (&UvcTimer);

#endif

           // if (glActiveSocket)

                CyU3PGpifSMSwitch(CX3_INVALID_GPIF_STATE, CX3_START_SCK1,

                        CX3_INVALID_GPIF_STATE, ALPHA_CX3_START_SCK1, CX3_GPIF_SWITCH_TIMEOUT);

//           // else

             //   CyU3PGpifSMSwitch(CX3_INVALID_GPIF_STATE, CX3_START_SCK0,

             //          CX3_INVALID_GPIF_STATE, ALPHA_CX3_START_SCK0, CX3_GPIF_SWITCH_TIMEOUT);

//

            CyU3PUsbLPMEnable ();

            doLpmDisable = CyTrue;

//#ifdef RESET_TIMER_ENABLE

            CyU3PTimerModify (&UvcTimer, TIMER_PERIOD, 0);

//#endif

        }

    }

}

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

Please let me know the reason for using Manual IN and Manual OUT channel.

Assuming that you want to implement DMA Override Mode, you don't need MANUAL IN and MANUAL OUT channel. You can use the MANY_TO_ONE_ MANUAL_DMA channel and override it using CyU3PDmaChannelSetupSendBuffer API

Please refer to the firmware in this thread How to send debug data out an existing dma channel  (USBUART example in the FX3 SDK) (refer attachment)

You can understand how to use a DMA channel in Override mode. You can also refer to C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\basic_examples\cyfxflashprog which uses CyU3PDmaChannelSetupSendBuffer and CyU3PDmaChannelSetupRecvBuffer API (DMA override mode)

From your previous response:

I can't catch the packet in the bushound,and then the second time get the buffer from the channel of glChHandleStreamOut,it will return the error of 0x45,the first time return is success.

>> The error 0x45 is the timeout error which occurs when the DMA buffer is not ready either FULL/EMPTY. Also,  the GPIF state machine is configured for two producer sockets and the DMA channel you created consists of one producer socket. I am not able to understand the logic behind the code in CyCx3UvcAppDmaCallback.

The header and trailer should be given by the CPU and not GPIF socket and then that buffer should be sent to USB socket.

According to your application, DMA override mode would work fine.

Please make it clear which method would you like t use to send a separate buffer for Header and trailer. Is it the DMA override mode?

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hi,Rashi,

       Thank you very much for your reply.I tried  the DMA override mode like the example that you reply with me.but I met a problem:

I modify the  CyCx3UvcAppDmaCallback function,now I can send the packet using the CyU3PDmaMultiChannelSetupSendBuffer,but  then I want to use the CyU3PDmaMultiChannelSetXfer function as your example ,but it return  error code 0x43.and the next package can't send out,

the dma channel seem to be abnormal.I don‘t hnow why?
        status = CyU3PDmaMultiChannelGetBuffer(chHandle, &DmaBuffer, CYU3P_NO_WAIT);
        while (status == CY_U3P_SUCCESS)
        {
            /* Add Headers*/
            if(DmaBuffer.count < CX3_UVC_DATA_BUF_SIZE)
            {
                CyCx3UvcAddHeader ((DmaBuffer.buffer - CX3_UVC_PROD_HEADER), CX3_UVC_HEADER_EOF);
                glHitFV = CyTrue;
                glFrameCount = 0;
            }
            else
            {

                        CyCx3UvcAddHeader ((DmaBuffer.buffer - CX3_UVC_PROD_HEADER), CX3_UVC_HEADER_FRAME);

                 if(glFrameCount == 0)
                 {
                    buf_p.buffer = trailer;
                    buf_p.status = 0;
                    buf_p.size    = 52;
                    buf_p.count   = 52;

                 CyU3PDmaMultiChannelReset (chHandle);
                    status =CyU3PDmaMultiChannelSetupSendBuffer(chHandle, &buf_p, 0);
                    if(status != 0)
                    {  

                              CyU3PDebugPrint(4,"\n\CyCx3UvcAppDmaCallback: status = %x\n", status);
                    }

                    CyU3PBusyWait(1000);
                    status =  CyU3PDmaMultiChannelSetXfer(chHandle,0,0);
                  if (status != CY_U3P_SUCCESS)
                 {
                        CyU3PDebugPrint(4,"\n\CyU3PDmaMultiChannelSetXfer: status = %x\n", status);
                       break;
                 }
        }

        glFrameCount = 1;
       }

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

Apologies. I shared the wrong firmware

Please let me know DMA channel type that you are using

The 0x43 error occurs when the DMA channel is not in configured state. CyU3PDmaMultiChannelSetXfer can only be called when DMA channel id in configured state. CyU3PDmaMultiChannelSetupSendBuffer  sets the DMA channelstate to DMA override. This is the reason for the error. That means you can't call CyU3PDmaMultiChannelSetXfer after CyU3PDmaMultiChannelSetupSendBuffer

Can you not put this API in the callback function and instead create a different function to  send the leader and trailer.

If this doesn't work, please share the firmware i.e " .c" files you are working on

Regards,

Rashi

Regards,
Rashi
0 Likes
haxu_299926
New Contributor

Hello,

    The DMA channel type that I used is MANUAL_MANY_TO_ONE.I can change the normal mode to the DMA override successful,but when I send the package use the CyU3PDmaMultiChannelSetupSendBuffer,I can't reutrn previous status.

    But I see the example of the cycx3_uvc_ov5640, in the CyCx3UvcApplnStart function,the operation is successfull,

    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;

    However, whether I create a thread or in DMA callback , when I execute CyU3PDmaMultiChannelSetXfer the CyU3PDmaMultiChannelReset, it always return 0x42

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

Please refer to the GPIF to USB example attached.

I have made certain changes to the default firmware. I am using CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE in override mode.

I have checked this firmware at my end. I am able to get the random values sent through the API CyU3PDmaMultiChannelSetupSendBuffer .(Refer Attachment)

As per your previous response. Error 0x42 - CY_U3P_ERROR_NOT_STARTED

I went through the source code CyU3PDmaMultiChannelSetXfer and CyU3PDmaMultiChannelReset do not check or return CY_U3P_ERROR_NOT_STARTED . There is some other API which is causing this error. Please confirm this.

I am not able to test the results using your firmware (due to host application constraints) .Please refer to GPIF to USB firmware and make similar changes to your firmware.

Regards,

Rashi

Regards,
Rashi

View solution in original post

0 Likes
haxu_299926
New Contributor

Hello,

        I want to know the meaning of gpif statemachine function CyU3PGpifGetSMState return value.

I can't find out what's meaning of these state code 0x83 and 0x84.

0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

You get State ID like 0x84 and 0x84 when there are mirror states in the GPIF state machine.

To know about the mirror states you can refer to section 7.7 of the FX3_TRM in the SDK.

You can also refer to this thread Find GPIF2 mirror state IDs

For eg: if third state in the GPIF state machine has a mirror state, the ID of that mirror state will be 0x83 (i.e 128+3)

Regards,

Rashi

Regards,
Rashi
0 Likes
Rashi_Vatsa
Moderator
Moderator

Hello,

I have implemented DMA Override Mode in GPIF to USB example of SDK. By default it reads the GPIF lines and commits to the USB block.The DMA channel is AUTO channel. (refer the attachment)

I am passing random values (10 bytes: highlighted in the snippet) in by overriding DMA  mode.

Once these bytes are sent the DMA channel is set to to  configured state by using : (this would work according to DMA configuration  passed through the handle glDmaChHandle

apiRetStatus = CyU3PDmaChannelSetXfer (&glDmaChHandle, CY_FX_GPIFTOUSB_DMA_TX_SIZE);

In your application, you need to start streaming after the header is sent and at the end of the frame again send the trailer. But this could lead to some data loss as there would be continuous input of from sensor and you would need to switch between DMA override mode and DMA manual (configured mode)

For you better understanding of DMA Override mode, you can also refer to FX3SRaid0 example in the SDK

Regards,

Rashi

Regards,
Rashi
0 Likes