Trying to use the FX3 to capture images from OnSemi image sensor and have few questions - could not find answer in the docs or forums. I use the image sensor in trigger mode, so need to read only 1 image upon request. The image size is known. For example: the buffer size of monochromatic image of 768X768 pixels is 768X768X2 = 1179648 bytes (16 bits per pixel) I use a GPIF to USB bulk manual channel to capture the image. Knowing this size: What should be the buffer size associated with the channel? (i now use size of 16*1024) What should be the number of buffers allocated to the channel (I use 4) What should be the packet size (I use 1024) When capturing images of 512X512 it works well. But when capturing images of 768X768 and bigger, the received buffer is made of 15-20 last lines of the previous image, and the rest are lines of the currently captured image. There is some sync problems between the captured and received buffers.Can anyone help with this?
Did not use the AN75779 because I use a triggered image (only one image at a time that is generated upon request)
I edited the simple GpifToUSB example.
==================This is the very simple DmaCallback:============================
// uint8_t high,low;
if (type == CY_U3P_DMA_CB_PROD_EVENT)
/*Change few pixels to black */
for(i=0; i<50; i++)
input->buffer_p.buffer[7680+i] = 0;
CyU3PDmaChannelCommitBuffer (chHandle, input->buffer_p.count, 0);
if (type == CY_U3P_DMA_CB_CONS_EVENT)
/* Data transfer has been started. Enable the LPM disable loop. */
gDoLpmDisable = CyTrue;
==================== This is the header with the relevant definitions. ======================
#define CY_FX_GPIFTOUSB_DMA_TX_SIZE (0) /* DMA transfer size is set to infinite */
#define CY_FX_GPIFTOUSB_THREAD_STACK (0x1000) /* Bulk loop application thread stack size */
#define CY_FX_GPIFTOUSB_THREAD_PRIORITY (8) /* Bulk loop application thread priority */
#define CY_FX_GPIFTOUSB_PATTERN (0xAA) /* 8-bit pattern to be loaded to the source buffers. */
/* Endpoint and socket definitions for the bulk source sink application */
#define CY_FX_EP_CONSUMER 0x83 /* EP 3 IN */
#define CY_FX_EP_CONSUMER_SOCKET CY_U3P_UIB_SOCKET_CONS_3 /* Socket 1 is consumer */
#define CY_FX_GPIF_PRODUCER_SOCKET CY_U3P_PIB_SOCKET_0
/* Burst mode definitions: Only for super speed operation. The maximum burst mode
* supported is limited by the USB hosts available. The maximum value for this is 16
* and the minimum (no-burst) is 1. */
/* Burst length in 1 KB packets. Only applicable to USB 3.0. */
#define CY_FX_EP_BURST_LENGTH (16)
/* Size of DMA buffers used by the application. Tried many values*/
#define CY_FX_DMA_BUF_SIZE (28800) // (26912) (16384) //(32768) (16384)
/* Number of DMA buffers to be used on the channel. */
#define CY_FX_DMA_BUF_COUNT (4)
/* Parameters for loop-back function. */
#define CY_FX_EP_LOOP_OUT (0x02)
#define CY_FX_EP_LOOP_IN (0x82)
#define CY_FX_LOOP_PRODUCER_SOCK CY_U3P_UIB_SOCKET_PROD_2
#define CY_FX_LOOP_CONSUMER_SOCK CY_U3P_UIB_SOCKET_CONS_2
#define STREAMING_MANUAL (1)
To ensure that the GPIF and DMA buffers are in sync, the DMA reset mechanism can be used after each transfer. Please check the AN75779 example for DMA reset procedure. Also as no control signals are used, there is no need for any actual device connectivity on the GPIF II interface when using gpiftousb example. How are you make sure that the data sampling is proper? How is the GPIF-II project modified? Please check the Slave FIFO GPIF interface attached with the app note AN65974 - Designing with the EZ-USB® FX3™ Slave FIFO Interface.
Like in the AN75779, the the GPIF reads the image data only when Frame and Line signals are on. The image contains a total of about 1M bytes. It starts only after specific request, and only 1 image is sent from the sensor. The first image is correct, but some how, the first few bytes of the next image that is initiated and read only few seconds after, contains some data of the prev image. What do you mean by "reset procedure"?
In the AN75779 CyFxUvcApplnStop function, the DMA channel and endpoint is cleared which will remove any previous image data already sampled. I am attaching the code corresponding to this.
/* Disable the GPIF state machine. */
streamingStarted = CyFalse;
glDmaResetFlag = CY_FX_UVC_DMA_RESET_EVENT_NOT_ACTIVE;
/* Place the EP in NAK mode before cleaning up the pipe. */
CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyTrue);
/* Reset and flush the endpoint pipe. */
CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyFalse);
Similarly in the CyFxUvcApplnStart the channel will be set ready for transfer.
Thanks for the info.
I believe that there should be a way to receive the images without resting or clearing the buffers.
It is weird that everything works fine if image size is up to 512X512X16 bits. Can not understand what goes wrong when receiving bigger images.
Can you help and tell where can I find a good documentation that explains the following:
Tried to read about these, but could not find good documentation.
AN75779 contains explanation of how the buffers are managed when a large stream of data is received from the GPIF. Also it is explained how to select a DMA buffer size to optimize USB throughput. Also you can go through FX3 programmers manual and FX3 TRM for more details which are available along with SDK.
With the current settings, this should work, but we need to conform the GPIF state machine is fine. Can you share the GPIF state machine. We can check how the data state machine is switching back to start receiving the new buffer.
Please see the above image for the state machine as designed for the project.
Regarding the documentation of the AN75779:
This is a quote from the "Ping Pong DMA buffers paragraph:
A socket takes a finite amount of time (up to a
few microseconds) to switch from one DMA Descriptor to another after it fills or empties a DMA buffer. The socket will
not be able to transfer any data while this switch is in progress.
The way I understand it, when the DMA buffer which I set its size in the
#define CY_FX_DMA_BUF_SIZE is filled, the system drained it (to where?, and what is the CY_FX_DMA_BUF_COUNT ? ).
Anyway, as you can see, I use a buffer size of 28800 (count = 4), and so this switching must happen when I receive a 512X512X16 bits (262,164 bytes). As I mentioned before, everything works fine when receiving these images. But when changing to 768X768X16 images, there is an unexplained data that accumulated from prev. images. That is received at the beginning of each new incoming image.
I must understand more about what happens when a buffer is filled, and can not find good documentation for that.
Since your state machine is using a single socket, the buffer switching will come into consideration. CY_FX_DMA_BUF_SIZE provides the buffer size allocated to the socket and the CY_FX_DMA_BUF_COUNT is the number of such buffers the DMA can queue. From the above mentioned firmware settings, it will queue 4 buffers of 16KB size.i.e, Once your 16KB gets filled the buffer will switch to next one(4 is the count used). This buffer switching happens multiple times in transferring a single frame as frame size is much higher than buffer size.
Since you use only a single producer socket, there will be a delay in buffer switching when the buffer is getting filled. This buffer switching delay is around 100us. To avoid this we use two producer sockets in AN75779 and switch the sampling thread(thread switch wont have delay) between the two sockets.
Now for 512x512x16 frame size and 16KB buffer size, exactly 16 lines(16x512x2 bytes) will be packed in each buffer. Here the horizontal blanking must be helping to hide the delay. In case of 768x768x16 frame size, the first buffer will be full with 10 full lines and a half line. Then the buffer switching delay will cause losing some lines of data. This can be a reason the higher resolution is not working proper. Still I wonder how the first frame is received properly.
What is the horizontal blanking time in 512x512x16 and 768x768x16 frame size? Also can you try keeping a buffer size multiple of lines for 768x768x16 and check whether this is helping.
I made the necessary changes to use multi Chanel, 2 sockets and 2 threads - did not solve the problem. (And I never got any ERROR returned from the commit buffer command or any other) I managed to get a good quality image by using a workaround: sampling of about 20 lines more then needed, and I use the received buffer from an offset. In this way I only use the "good" part of the image.
During the tests I made while changing my program I noticed that there are unexpected effects of the length of lines, and limits of the GPIF counters. It works well only when there are some very specific relations between the two values. Can anyone explain?
Found a work around.
Data flows from the device to the host continuously only when the multi channel buffer size is set to a number that is a multiply of 1024
although that according o the docs, the buffer size should be a multiply of 16. The burst length is set to 16 (not sure if it is relevant) and the host is a Linux machine. The buffer size of the URB on the Linux size is set to the size of the complete image, and it returns full with the image data. For now, this is good enough for me, but not sure that this is the best way to go.