- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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):
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.