Can't seem to get data out of DMA

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

cross mob
lock attach
Attachments are accessible only for community members.
ThAl_4704151
Level 4
Level 4
25 sign-ins 25 replies posted 10 replies posted

Hello all,

With some help from the forum, I was able to get the chip to enumerate the other day, and now that that's working, I'm trying to send data through it using DMA to get the data from the host. I've tried to copy the USBBulkLoopManualInOut project.

To configure the endpoint, I:

  1. call CyU3PSetEpConfig()
    1. ep == <endpoint address parsed out of the descriptor, 0x02, 0x04 for output, and 0x86, 0x88 for input
    2. enable = CyTrue
    3. epType = <a type code I parsed out of the descriptor, in this case interrupt>
    4. burstLen = 1
    5. streams = 0
    6. pcktSize = <also parsed out of the descriptor, in this case, either 256 or 512
  2. call CyU3PDmaChannelCreate()
    1. pass in a pointer to a CyU3PDmaChannel in my endpoint struct to keep track of it
    2. CyU3PDmaType_t type is CY_U3P_DMA_TYPE_MANUAL_OUT if the high bit of the endpoint address is 1, and CY_U3P_DMA_TYPE_MANUAL_IN otherwise
    3. if the high bit of the endpoint address is 1, the prodSckId is CY_U3P_UIB_SOCKET_PROD_0 + <the numeric part of the endpoint address, and the consSckId is CY_U3P_CPU_SOCKET_CONS. Otherwise, the prodSckId  is CY_U3P_CPU_SOCKET_PROD and the consSckId is CY_U3P_UIB_SOCKET_CONS_0 + the numeric part of the endpoint address.
    4. dmaMode = CY_U3P_DMA_MODE_BYTE
    5. notification, prodHeader, prodFooter, consHeader, prodAvailCount are all 0
    6. cb is NULL
  3. call CyU3PDmaChannelSetXfer
    1. pass in the same pointer to a CyU3PDmaChannel, and zero for unlimited transfers
  4. call CyU3PUsbFlushEp, passing the address from before. Originally I didn't have this, but I figured it couldn't hurt.

So far so good. Nothing returns an error code.

When I go to get data, I:

  1. call a function I've written to get the CyU3PDmaChannel pointer for the address 2.
    1. Address 2 is supposed to be an endpoint that will allow me to receive data from the host.
    2. I've verified with the debugger that it's returning the same handle out of my endpoint struct for the endpoint address I put in.
  2. I've tried calling CyU3PDmaChannelResume here with that pointer to enable both producer and consumer, but it doesn't seem to do anything.
  3. call CyU3PDmaChannelGetBuffer(<the previously mentioned pointer>, the address of a buffer struct, either CYU3P_WAIT_FOREVER or CYU3P_NO_WAIT)
    1. NO_WAIT returns a timeout immediately, even once I've sent data from the Control Center
    2. WAIT_FOREVER doesn't return at all, even once I've sent data from the Control Center
  4. CyU3PDmaChannelDiscardBuffer to clean up the buffer.

I'll include my source code, but does anyone know what I'm missing, or what I've done wrong?

Thank you for your help!

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Hello,

I tried to reproduce the issue at my end and was successful in that. After debugging the firmware I realized that the configureEndpoints() is called just after the CyU3PConnectState API.

configureEndpoints() which is equivalent to CyFxBulkLpApplnStart of the Manual IN OUT example should be called when the CY_U3P_USB_EVENT_SETCONF event occurs. For this USB event call back needs to be registered and events needs to be handled.

********************************************************************

CyU3PUsbRegisterEventCallback(usbEventCallback);

void usbEventCallback(

        CyU3PUsbEventType_t evtype,    /**< The event type. */

        uint16_t            evdata      /**< Event specific data. */

        ){

switch (evtype)

    {

        case CY_U3P_USB_EVENT_SETCONF:

            /* Disable the low power entry to optimize USB throughput */

            CyU3PUsbLPMDisable();

            /* Stop the application before re-starting. */

            if (glIsApplnActive)

            {

            disableendpoint();

            }

            /* Start the loop back function. */

            configureEndpoints ();

            break;

        case CY_U3P_USB_EVENT_RESET:

        case CY_U3P_USB_EVENT_DISCONNECT:

            /* Stop the loop back function. */

            if (glIsApplnActive)

            {

                disableendpoint();  //equivalent to AppStop

            }

            break;

        default:

            break;

    }

***************************************************************

Please find the attached modified firmware and test results. Now, you can try calling the CyU3PDmaChannelGetBuffer as done in the SDK example.

Please let me know if any queries on this

Regards,

Rashi

Regards,
Rashi

View solution in original post

4 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

From the source code that you shared i understand that only one channel is created at a time i.e. either Manual In (USB>CPU) or Manual OUT (CPU>USB) unlike USBBulklpManualnOut which has both the channels created.

To check if the data is received by the USB socket you can add the callback to the DMA channel configuration and register for the PROD and CONS event.

***************For the MANUAL IN channel only****************

/* Create a DMA MANUAL_IN channel for the producer socket. */

    dmaCfg.size  = size;

    dmaCfg.count = CY_FX_BULKLP_DMA_BUF_COUNT;

    dmaCfg.prodSckId = CY_FX_EP_PRODUCER_SOCKET;

    dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;

    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

   dmaCfg.notification =  CY_U3P_DMA_CB_PROD_EVENT;

    dmaCfg.cb = CyFxDmaCallback;

    dmaCfg.prodHeader = 0;

    dmaCfg.prodFooter = 0;

    dmaCfg.consHeader = 0;

    dmaCfg.prodAvailCount = 0;

In the CyFxDmaCallback function CY_U3P_DMA_CB_PROD_EVENT can be tracked using a variable and then later the value of the variable can be printed.

void CyFxDmaCallback (

        CyU3PDmaChannel   *chHandle, /* Handle to the DMA channel. */

        CyU3PDmaCbType_t  type,      /* Callback type.             */

        CyU3PDmaCBInput_t *input)    /* Callback status.           */

{

    if (type == CY_U3P_DMA_CB_PROD_EVENT)

    {

        glDMARxCount ++;

     }

}

Get the variable printed in the for{} to check if the data is received at USB socket

  for (;;)

    {

    CyU3PDebugPrint (4, "\n\n glDMARxCount = %d", glDMARxCount);

.....

}

*********************************************************************

>> If from the above test you get CY_U3P_DMA_CB_PROD_EVENT for MANUAL_IN channel try calling CyU3PDmaChannelGetBuffer inside the callback under CY_U3P_DMA_CB_PROD_EVENT and let me know the results.

Q1 call a function I've written to get the CyU3PDmaChannel pointer for the address 2.

>> Please confirm that the UIB socket used in DMA channel and the endpoint used are same (for example if UIB socket is PROD_1 then EP number should also be OUT endpoint 1 (0x01)

Q2 I've tried calling CyU3PDmaChannelResume here with that pointer to enable both producer and consumer, but it doesn't seem to do anything.

>> Please comment out these  CyU3PDmaChannelGetBuffer &CyU3PDmaChannelResume  API  for the above mentioned test.

Q3 call CyU3PDmaChannelGetBuffer(<the previously mentioned pointer>, the address of a buffer struct, either CYU3P_WAIT_FOREVER or CYU3P_NO_WAIT)

>> CYU3P_WAIT_FOREVER will wait for buffer till infinite timer ticks

>> CYU3P_NO_WAIT will not wait for buffer and return immediately

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hi Rashi,

First off, thanks for your help. You're a life saver.

I was able to try to use the callback like you suggested, but it doesn't seem to ever get called when I try to send data. I attached the callback in usb.c in the configureEndpoints function.

I was able to determine which sockets were being used with which endpoints (out 2 with PROD_2, out 4 with PROD_4, in 6 with CONS_6, and in 8 with CONS_8). By printing out the addresses of the CyU3PDmaChannels, I was able to verify that when I pass my function an endpoint address, I get the CyU3PDmaChannel associated with the correct UIB socket.

I made a couple other changes too. I was originally not using the UART logging, and instead just relying on the debugger and blinking the LED on the demo board. It turns out the LED was attached to one of the pins needed for UART, and by configuring it as GPIO, I broke UART, so I fixed that. I'm attaching the new code to this reply.

Again, thanks for your help.

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

Hello,

I tried to reproduce the issue at my end and was successful in that. After debugging the firmware I realized that the configureEndpoints() is called just after the CyU3PConnectState API.

configureEndpoints() which is equivalent to CyFxBulkLpApplnStart of the Manual IN OUT example should be called when the CY_U3P_USB_EVENT_SETCONF event occurs. For this USB event call back needs to be registered and events needs to be handled.

********************************************************************

CyU3PUsbRegisterEventCallback(usbEventCallback);

void usbEventCallback(

        CyU3PUsbEventType_t evtype,    /**< The event type. */

        uint16_t            evdata      /**< Event specific data. */

        ){

switch (evtype)

    {

        case CY_U3P_USB_EVENT_SETCONF:

            /* Disable the low power entry to optimize USB throughput */

            CyU3PUsbLPMDisable();

            /* Stop the application before re-starting. */

            if (glIsApplnActive)

            {

            disableendpoint();

            }

            /* Start the loop back function. */

            configureEndpoints ();

            break;

        case CY_U3P_USB_EVENT_RESET:

        case CY_U3P_USB_EVENT_DISCONNECT:

            /* Stop the loop back function. */

            if (glIsApplnActive)

            {

                disableendpoint();  //equivalent to AppStop

            }

            break;

        default:

            break;

    }

***************************************************************

Please find the attached modified firmware and test results. Now, you can try calling the CyU3PDmaChannelGetBuffer as done in the SDK example.

Please let me know if any queries on this

Regards,

Rashi

Regards,
Rashi

That did the trick. Thank you!

0 Likes