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

USB superspeed peripherals Forum Discussions

AlEr_4025481
Level 2
Level 2
10 replies posted 5 replies posted 5 questions asked

Hello,

I took basic cyfxgpiftousb example from c:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\firmware\basic_examples\ and added CyU3PPibRegisterCallback to the sources to see if there is some events happen during GPIF to DMA transfer. I was surprised a lot when I saw in output CYU3P_PIB_ERR_THR0_WR_OVERRUN errors.

debug initialized

USB event: 11 0

About to connect to USB host

USB event: 0 1

CY_U3P_USB_EVENT_CONNECT detected

CyFxApplnInit complete

USB event: 4 1

USB event: 8 0

USB event: 5 1

GpifToUsbDmaCallback: 32768 bytes commited

GpifToUsbDmaCallback: 32768 bytes commited

GpifToUsbDmaCallback: 32768 bytes commited

GpifToUsbDmaCallback: 32768 bytes commited

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

As I think these error happen while IN_DATA action trying to work during DMA buffers are switching. Am I right? If so, how can I pause the data input process until next buffer will be ready? My modified source code is attached.

0 Likes
1 Solution
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Please use the debug library which is posted in post number 11 of commit error and back flow error in UVC AN75779 and test

(Note: This library is just for debug purpose and should not be considered as standard release)

In your firmware, make changes to PROD_EVENT handling in GpifToUsbDmaMultiCallback as below:

if (type == CY_U3P_DMA_CB_PROD_EVENT)

    {

        /* Since this is a many to one channel, there can be a case where one producer

         * is faster than the other out of sequence produce events. This means that

         * we have to check for buffers with all producer sockets. In this case there

         * are two producers and so loop twice or until there are valid buffers. */

        for (index = 0; index < 2; index++)

        {

            status = CyU3PDmaMultiChannelGetBuffer (chHandle, &buf_p, CYU3P_NO_WAIT);

            if (status != CY_U3P_SUCCESS)

            {

            CyU3PDebugPrint (4, "GetFail\r\n");

                /* This can be a valid case. Just break. */

                break;

            }

            else

            {

            buf_p.buffer[0x0000] = DataSignature++;

            buf_p.buffer[buf_p.count - 1] = DataSignature++;

            /* 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. */

            status = CyU3PDmaMultiChannelCommitBuffer (chHandle, buf_p.count, 0);

            if (status != CY_U3P_SUCCESS)

            {

            CyU3PDebugPrint (4, "CyU3PDmaMultiChannelCommitBuffer failed, index = %d, Error code = %d\r\n", index, status);

            } else

            CyU3PDebugPrint (4, "GpifToUsbDmaMultiCallback: %d bytes commited, index = %d\r\n", buf_p.count, index);

            }

        }

        /* Increment the counter. */

        //glDMARxCount++;

    }

}

Please, also note that, it is not recommended to place DebugPrints in dmacallbacks. (You can do it now just for testing)

In multi channel, the dma buffers should be filled and emptied in a pingpong fashion.

Regards,

Hemanth

Hemanth

View solution in original post

0 Likes
7 Replies
AlEr_4025481
Level 2
Level 2
10 replies posted 5 replies posted 5 questions asked

Just modified again source code above closer to my real task. I switched GPIF state machine to master async mode with one RD output. All I need at this moment is collecting 16-bit words with automatically RD strobing. As I see CYU3P_PIB_ERR_THR0_WR_OVERRUN still happens.

2020-07-21_11-49-49.png

2020-07-21_11-49-04.png

debug initialized

USB event: 11 0

About to connect to USB host

CyFxApplnInit complete

USB event: 2 0

USB event: 0 0

CY_U3P_USB_EVENT_CONNECT detected

USB event: 4 0

USB event: 6 1

USB event: 4 0

USB event: 6 1

USB event: 5 1

GpifToUsbDmaCallback: 32768 bytes commited

CYU3P_PIB_ERR_THR0_WR_OVERRUN

GpifToUsbDmaCallback: 32768 bytes commited

CYU3P_PIB_ERR_THR0_WR_OVERRUN

GpifToUsbDmaCallback: 32768 bytes commited

CYU3P_PIB_ERR_THR0_WR_OVERRUN

GpifToUsbDmaCallback: 32768 bytes commited

CYU3P_PIB_ERR_THR0_WR_OVERRUN

0 Likes

Well, my brain damage continues. I modified state machine as shown below and replaced CyU3PDmaChannelConfig_t by CyU3PDmaMultiChannelConfig_t. It looks like CYU3P_PIB_ERR_THR0_WR_OVERRUN finally gone, but DMA commit errors happen.

2020-07-21_15-36-39_LBL.png

My DMA multi channel config:

CyU3PDmaMultiChannelConfig_t dmaMCfg;

    dmaMCfg.size  = 1024;

    dmaMCfg.count = 1;

    dmaMCfg.validSckCount = 2;

    dmaMCfg.prodSckId[0] = CY_U3P_PIB_SOCKET_0;

    dmaMCfg.prodSckId[1] = CY_U3P_PIB_SOCKET_1;

    dmaMCfg.consSckId[0] = CY_FX_EP_CONSUMER_SOCKET;

    dmaMCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

    dmaMCfg.prodHeader = 0;

    dmaMCfg.prodFooter = 0;

    dmaMCfg.consHeader = 0;

    dmaMCfg.prodAvailCount = 0;

    dmaMCfg.notification = CY_U3P_DMA_CB_CONS_SUSP | CY_U3P_DMA_CB_PROD_EVENT;;

    dmaMCfg.cb = GpifToUsbDmaMultiCallback;

My GpifToUsbDmaMultiCallback:

void

GpifToUsbDmaMultiCallback (

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

        CyU3PDmaCbType_t      type,     /* Callback type.             */

        CyU3PDmaCBInput_t    *input)    /* Callback status.           */

{

    uint8_t index = 0;

    CyU3PDmaBuffer_t buf_p;

    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    CyU3PDebugPrint (4, "GpifToUsbDmaMultiCallback called\r\n");

...

            buf_p.buffer[0x0000] = DataSignature++;

            buf_p.buffer[buf_p.count - 1] = DataSignature++;

...

}

Debug output:

debug initialized

USB event: 11 0

About to connect to USB host

CyFxApplnInit complete

USB event: 2 0

USB event: 0 0

CY_U3P_USB_EVENT_CONNECT detected

USB event: 4 0

USB event: 6 1

USB event: 4 0

USB event: 6 1

USB event: 5 1

GpifToUsbDmaMultiCallback called

GpifToUsbDmaMultiCallback: 1024 bytes commited, index = 0

GpifToUsbDmaMultiCallback: 1024 bytes commited, index = 1

GpifToUsbDmaMultiCallback called

CyU3PDmaMultiChannelCommitBuffer failed, index = 0, Error code = 71

CyU3PDmaMultiChannelCommitBuffer failed, index = 1, Error code = 71

First 1024 bytes received with wrong signature (must be 0x0000 at the beginning and 0x0001 at the end):

2020-07-21_16-07-23.png

So now my questions are:

1. Why buffer commit errors happen?

2. Why DataSignature at the beginning and at the end of the buffer is incorrect?

0 Likes

I'm totally stuck! Error code 71 means CY_U3P_ERROR_INVALID_SEQUENCE (invalid function call sequence). Can't imagine what exactly I'm doing wrong...

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Please use the debug library which is posted in post number 11 of commit error and back flow error in UVC AN75779 and test

(Note: This library is just for debug purpose and should not be considered as standard release)

In your firmware, make changes to PROD_EVENT handling in GpifToUsbDmaMultiCallback as below:

if (type == CY_U3P_DMA_CB_PROD_EVENT)

    {

        /* Since this is a many to one channel, there can be a case where one producer

         * is faster than the other out of sequence produce events. This means that

         * we have to check for buffers with all producer sockets. In this case there

         * are two producers and so loop twice or until there are valid buffers. */

        for (index = 0; index < 2; index++)

        {

            status = CyU3PDmaMultiChannelGetBuffer (chHandle, &buf_p, CYU3P_NO_WAIT);

            if (status != CY_U3P_SUCCESS)

            {

            CyU3PDebugPrint (4, "GetFail\r\n");

                /* This can be a valid case. Just break. */

                break;

            }

            else

            {

            buf_p.buffer[0x0000] = DataSignature++;

            buf_p.buffer[buf_p.count - 1] = DataSignature++;

            /* 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. */

            status = CyU3PDmaMultiChannelCommitBuffer (chHandle, buf_p.count, 0);

            if (status != CY_U3P_SUCCESS)

            {

            CyU3PDebugPrint (4, "CyU3PDmaMultiChannelCommitBuffer failed, index = %d, Error code = %d\r\n", index, status);

            } else

            CyU3PDebugPrint (4, "GpifToUsbDmaMultiCallback: %d bytes commited, index = %d\r\n", buf_p.count, index);

            }

        }

        /* Increment the counter. */

        //glDMARxCount++;

    }

}

Please, also note that, it is not recommended to place DebugPrints in dmacallbacks. (You can do it now just for testing)

In multi channel, the dma buffers should be filled and emptied in a pingpong fashion.

Regards,

Hemanth

Hemanth
0 Likes

Hi Hemanth,

Thanks a lot for your reply! I have done as you said, placed libcyfxapi.a to c:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\fw_lib\1_3_4\fx3_debug\ and switched to debug build. My GpifToUsbDmaMultiCallback now includes:

    if (type == CY_U3P_DMA_CB_PROD_EVENT)

    {

        /* Since this is a many to one channel, there can be a case where one producer

         * is faster than the other out of sequence produce events. This means that

         * we have to check for buffers with all producer sockets. In this case there

         * are two producers and so loop twice or until there are valid buffers. */

        for (index = 0; index < 2; index++)

        {

            status = CyU3PDmaMultiChannelGetBuffer (chHandle, &buf_p, CYU3P_NO_WAIT);

            if (status != CY_U3P_SUCCESS)

            {

                 CyU3PDebugPrint (4, "GetFail\r\n");

                 /* This can be a valid case. Just break. */

                 break;

            } else {

            buf_p.buffer[0x0000] = DataSignature++;

            buf_p.buffer[buf_p.count - 1] = DataSignature++;

            /* 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. */

            status = CyU3PDmaMultiChannelCommitBuffer (chHandle, buf_p.count, 0);

            if (status != CY_U3P_SUCCESS)

            {

                 CyU3PDebugPrint (4, "CyU3PDmaMultiChannelCommitBuffer failed, index = %d, Error code = %d\r\n", index, status);

            } else

                 CyU3PDebugPrint (4, "GpifToUsbDmaMultiCallback: %d bytes commited, index = %d\r\n", buf_p.count, index);

            }

        }

My debug output as soon as code started:

debug initialized

USB event: 11 0

About to connect to USB host

CyFxApplnInit complete

USB event: 2 0

USB event: 0 0

CY_U3P_USB_EVENT_CONNECT detected

USB event: 4 0

USB event: 6 1

USB event: 4 0

USB event: 6 1

USB event: 5 1

GpifToUsbDmaMultiCallback called

GpifToUsbDmaMultiCallback: 1024 bytes commited, index = 0

GpifToUsbDmaMultiCallback: 1024 bytes commited, index = 1

GpifToUsbDmaMultiCallback called

GetFail

Every time I receive 1024 bytes from 0x81 bulk EP three lines are add:

GpifToUsbDmaMultiCallback called

GpifToUsbDmaMultiCallback: 1024 bytes commited, index = 0

GetFail

Data signature in the buffers increments correctly: 0x0000-0x0001, 0x0002-0x0003 and so on.

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Yes, the above logs are as expected. GetFail which is seen in line 17 of debug output is because both the buffers of the channel are committed to USB. GetFail in line 3 of last snippet is because only 1 buffer is made available by PIB block with data to commit to USB.

FYI:

1. Assume that dmaMCfg.count is 2 -> in which case socket 0 will have 2 buffers (name it buffer1 , buffer2) and socket 1 will have 2 buffers (name it buffer3, buffer4). Total 4.

2. Let's say the following are filled -> buffer1, buffer2

3. In this case, first call to CyU3PDmaMultiChannelGetBuffer() will pass which would give buffer1 to commit to USB. But next call for CyU3PDmaMultiChannelGetBuffer() would fail as expects buffer3 next -> this is the ping pong requirement which I mentioned in my last post. -> CyU3PDmaMultiChannelGetBuffer() will not succeed even though buffer2 is full instead it now looks at socket1's buffer.

Regards,

Hemanth

Hemanth
0 Likes

Hi Hemanth,

thanks for your explanation, it's very helpful for me. Later I plan to attach FPGA with a counter on data bus, to be sure that buffers are switching correctly and received data is monotonic.

At this moment I think this thread can be closed.

0 Likes