FX3 data lost during DMA transfer

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.
AlEr_4025481
Level 2
Level 2
10 replies posted 5 replies posted 5 questions asked

Hi there,

I'm fighting with data lost during DMA transfer and totally stuck on two questions... To be sure that received data is monotonic I attached an FPGA which works as a basic counter. FPGA sends to FX3 512 byte blocks, each block filled by 16-bit block number. For example, first 512 bytes of data filled by 0x0000, 2nd 512 bytes filled by 0x0001, 3rd 512 bytes filled by 0x0002 and so on. Verilog source code is below.

module main(

    input RD,

    input RST,

    output [15:0] DATA,

output LED

    );

reg [23:0] counter;

always @(negedge RST or posedge RD)

begin

if (!RST)

counter <= 0;

else

counter <= counter + 24'd1;

end

assign DATA = counter[23:8];

assign LED = counter[13];

endmodule

FX3 GPIF configured as master async device, each DATA_IN action asserts RD output.

2020-08-02_21-38-37.png

DMA configuration:

    dmaCfg.size = 16384;

    dmaCfg.count = 1;

    dmaCfg.prodSckId = CY_U3P_PIB_SOCKET_0;

    dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_1;

    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

    dmaCfg.notification = 0;

    dmaCfg.cb = NULL;

    dmaCfg.prodHeader = 0;

    dmaCfg.prodFooter = 0;

    dmaCfg.consHeader = 0;

    dmaCfg.prodAvailCount = 0;

As soon as vendor code received data transfer starts with CyU3PGpifSMSwitch() API. Every tyme I'm trying to get exactly 16384 bytes of data through bulk IN EP, no less, no more, because GPIF SM uses LD_DATA_COUNT action and grabs only 8192 words (16384 bytes). But unfortunately sometimes I see a data lost in the MIDDLE of transfer. Sometimes data received correctly, sometimes not. And as I see when data lost happens, it's always happens at the same offset between 0x0008 and 0x0009 words as on the 3rd picture below.

2020-08-02_21-23-11.png

2020-08-02_21-27-15.png

2020-08-02_21-29-36.png

So my first question is what I missed? Should I change something in GPIF or DMA config?

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

Hello,

I have tested the attached firmware at my end.

1) I have pulled up DQ[15] pin and then passed the vendor command. On transfer IN I don't see the data loss

2) For the second test,I have pulled up DQ[1] pin and then passed the vendor command. I don't see the data loss in this case as well

Here are the debug prints for the same

teraterm_prints.PNG

From this test, we can confirm that the problem is not on the FX3 hardware but it might be in the synchronization between FX3 (IN DATA) and FPGA (DATA_OUT).

There is a possibility that data is not in sync with the DATA IN of FX3.

To confirm that we would need the traces of data lines (16 bit) along with the RD signal. Please probe the data bus along with the RD signals and share the traces.

Regards,

Rashi

Regards,
Rashi

View solution in original post

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

Another problem concerns GPIO and GPIF. As you see above my FPGA has reset input, reset happens when it asserts from high to low (on negative adge). So my FX3 source code uses DQ16 pin as reset output for FPGA.

#define FPGA_RST_GPIO (33) /* FX3 DQ16 pin */

...

gpioConfig.inputEn = CyFalse; // Configured as output

gpioConfig.outValue = CyTrue; // Default RST level is HIGH (inactive state)

gpioConfig.driveLowEn = CyTrue;

gpioConfig.driveHighEn = CyTrue;

gpioConfig.intrMode = CY_U3P_GPIO_NO_INTR;

apiRetStatus = CyU3PDeviceGpioOverride (FPGA_RST_GPIO, CyTrue);

...

apiRetStatus = CyU3PGpioSetSimpleConfig(FPGA_RST_GPIO, &gpioConfig);

...

When reset output physically connected to FPGA every requested 16384 bytes of data starts from 0x0000 pattern (1st 512 bytes filled by 0x0000, 2nd 512 bytes filled by 0x0001 and so on). I mean it looks like reset output was toggled (driven from high to low) however my code do not uses CyU3PGpioSetValue(). As I see it happens when GPIF state machine reaches the final state. And as soon as I disconnect reset wire received data back to normal view, first 16384 bytes includes patterns from 0x0000 to 0x001F,  second 16384 bytes includes pattern from 0x0020 do 0x003F and so on.

Is this normal for overridden GPIO? What I should to do to leave GPIO completely untouched when GPIF switches many tymes?

0 Likes

Hello,

Are you facing the data loss while you try to transfer the first 16384 bytes? Or is it like the data loss is seen after you transfer multiple 16384 bytes? According to my understanding, you always transfer 16384 bytes from the FPGA to FX3. So, you can use the transition equation from STATE1 to STATE2 as !DATA_CNT_HIT.

From the state machine and firmware, I understand that a vendor command is used to start the collection of data. Upon receiving this vendor command, the state machine switches to MYSTART state. Instead of this implementation can you try the following:

1. Initially the state machine goes to IDLE state which is a start state.

2. From IDLE, it transitions to STATE3.

3. In STATE3, INTR_CPU is used. So the state machine passes the control to firmware (CyFxIntrCallback).

4. In the function CyFxIntrCallback, check if the vendor command is received or not. This can be done by setting a global variable upon reception of the vendor command and checking the value of the global variable inside the function CyFxIntrCallback.

5. If the value of the global variable is not set, then call the API CyU3PGpifControlSWInput(CyFalse). Please check the description of this API from the API guide.

6. If the value of global variable is set, then reset the global variable and call the API CyU3PGpifControlSWInput(CyTrue).

7. Remove the API CyU3PGpifSMSwitch in the vendor command implementation.

8. Also, please try de-selecting the Repeat actions until next transition for STATE1.

9. Use the state machine whose snapshot is attached below:

pastedImage_1.png

Please try these and let me know if you are seeing any improvements.

Best Regards,

Jayakrishna

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

Hi Jayakrishna,

Thanks for your reply!

Are you facing the data loss while you try to transfer the first 16384 bytes? Or is it like the data loss is seen after you transfer multiple 16384 bytes?

Data lost happens in random order, sometimes it happens in the first 16384 byte block (right after FX3 firmware started and 1st vendor command 0x00AB received), sometimes that first block may be transferred without data lost, but in this case data lost happens in next block.

According to my understanding, you always transfer 16384 bytes from the FPGA to FX3. From the state machine and firmware, I understand that a vendor command is used to start the collection of data. Upon receiving this vendor command, the state machine switches to MYSTART state.

Yes, that's absolutely correct.

I did as your explained, but FX3 freezes right after CyU3PGpifSMStart(). I don't see any debug messages from my main thread loop and blue led is not blinking:

// This loop is not executed  

for (;;)

    {

    CyU3PGpioSetValue(LED_GPIO, CyFalse);

        CyU3PThreadSleep (250);

    CyU3PGpioSetValue(LED_GPIO, CyTrue);

        CyU3PThreadSleep (1750);

    CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "EP0 requests count (%d), interrupt count (%d)\r\n",

    request_counter, gpif_intr_counter);

    }

My state machine looks like:

2020-08-03_21-19-27.png

Modified part of my source code:

...

volatile CyBool_t gpif_fw_triggered = CyFalse;

...

void CyFxIntrCallback(uint8_t stateId)

{

     gpif_intr_counter++;

     if (gpif_fw_triggered == CyTrue)

     {

          gpif_fw_triggered = CyFalse;

          CyU3PGpifControlSWInput(CyTrue);

     } else

          CyU3PGpifControlSWInput(CyFalse);

}

...

CyBool_t CyFxUsbSetupCB (uint32_t setupdat0, uint32_t setupdat1)

{

...

     gpif_fw_triggered = CyTrue;

     //apiRetStatus = CyU3PGpifSMSwitch(256, MYSTART, 256, ALPHA_MYSTART, 0);

...

}

Full sources are attached.

0 Likes

Still waiting for help...

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

Hello,

Please find the attached firmware with modifications in the GPIF state machine and firmware

Modifications to state machine are as follows:

sm.PNG

Initially, when the state machine is started it will go to STATE3 and do nothing. As soon as Vendor command (AB) is sent from the host the GPIF state machine will transition to State0.

In State1 the option of repeat actions until next transition is disabled so that counter increments only when there is a Data IN

And when one block of data is read or data counter hits there will be an interrupt to CPU and GPIF state machine will again go to State 3 and wait for next vendor command

Please test this firmware and let me know results

Regards,

Rashi

Regards,
Rashi
0 Likes

Hello again,

I spent a lot of time for experiments and result are still bad. First, I have added one more state to GPIF:

2020-08-05_13-21-06.png

Then I made sure that FX3 generates exactly 8192 RD pulses:

2020-08-05_12-49-54.png

First received 16384 shown below:

2020-08-05_12-56-40.png

2020-08-05_13-03-10.png

2020-08-05_13-06-53.png

As you can see there is two huge problems:

1. Data lost ALWAYS starts from offset 0x21FC, from each 16384 bytes two 16-bit words (four bytes) are lost.

2. Also data lost happens BETWEEN receiving each 16384 bytes. On the last two pictures only 508 bytes filed by 0x0020, two 16-bit words (four bytes) are lost.

I have to say checking or unchecking "repeat actions until next transaction" on STATE1 (or any other state N) changes nothing. I even tried to use other lines as RD (CTL1, CTL2, CTL3 and so on) - nothing changes too. I thought about electrical noises, but my wires are short (~10 cm) and three GND wires are between FX3 and FPGA. Also my FPGA works well with Arduino Due, no data lost happens.

Is it possible my FX3 has some kind of hardware bug?

DSCN9142.JPG

0 Likes

Hello,

Please try this state machine with some modifications and let me know the results

sm_1.PNG

- After modifying the state machine please check the RD toggle is proper as checked in your response i.e. 8192 transitions  from low to high

- Along with the changes in the state machine, please do the following changes in the firmware

1) Change the DMA channel from CY_U3P_DMA_TYPE_AUTO to CY_U3P_DMA_TYPE_AUTO_SIGNAL

2) Change the DMA channel configuration by registering for PROD/CONS events and DMA callback

    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

    dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

    dmaCfg.cb = CyFxDmaCallback; //NULL;

    dmaCfg.prodHeader = 0;

    dmaCfg.prodFooter = 0;

    dmaCfg.consHeader = 0;

    dmaCfg.prodAvailCount = 0;

   

    apiRetStatus = CyU3PDmaChannelCreate (&DmaChInHandle, CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaCfg);

    if (apiRetStatus != CY_U3P_SUCCESS)

    {

        CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "CyU3PDmaChannelCreate failed, Error code = %d\r\n", apiRetStatus);

        CyFxAppErrorHandler (apiRetStatus);

    }

3) In the DMA callback track, the Prod and Cons event and later print it in the for{} loop

*************Add this to the code***************

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++;      // global variable

    }

    if (type == CY_U3P_DMA_CB_CONS_EVENT)

    {

        glDmaTxCount++;    // global variable

    }

}

Print the values of the variables used for tracking the events

for (;;)

    {

        CyU3PThreadSleep (1000);

        if (glIsApplnActive)

        {

            /* Print the number of buffers received so far from the USB host. */

            CyU3PDebugPrint (6, "Data tracker: RxCount: %d, TxCount: %d\r\n", glDMARxCount, glDmaTxCount);

        }

.....

}

4) After passing the vendor command (for the first time) please check that the PROD event   ( RxCount)  has incremented or not. After the RxCount incremented  (i.e.e the DMA buffer is full /ready to be consumed) do a Transfer IN (BULK IN).

Note: Transfer IN (BULK IN transfer) should not be done before  RxCount is incremented

Please share the debug prints.

If possible probe the data lines (16-bit data bus) along with the RD signal and share the traces.

Please let me know if any queries on this.

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

Thanks a lot for your reply. I understand your idea, I will try it tomorrow and share the results.

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

Hi Rashi,

I modified my source code according your advice, and now it looks like state machine works wrong. When first vendor command received GPIF makes less than 8192 RD pulses. My logic analyzer counts 8189 full pulses and last pulse not completed (was not togged from low to high).

2020-08-06_12-09-11.png

Received data is not correct, two words are still missing at the same offset 0x21FC.

2020-08-06_12-37-34.png

Debug output:

Event: CY_U3P_USB_EVENT_VBUS_VALID

Event: CY_U3P_USB_EVENT_CONNECT

Initialization completed.

Event: CY_U3P_USB_EVENT_SET_SEL

Event: CY_U3P_USB_EVENT_SETCONF

Connected to Super-Speed host.

Unknown EP0 request received

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0) <<< Vendor command sent here

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

...

CYU3P_PIB_ERR_THR0_WR_OVERRUN <<< A lot of CYU3P_PIB_ERR_THR0_WR_OVERRUN

...

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

glDmaRxCount (1), glDmaTxCount (0)

CYU3P_PIB_ERR_THR0_WR_OVERRUN

CYU3P_PIB_ERR_THR0_WR_OVERRUN

...

CYU3P_PIB_ERR_THR0_WR_OVERRUN <<< A lot of CYU3P_PIB_ERR_THR0_WR_OVERRUN

...

As I found CYU3P_PIB_ERR_THR0_WR_OVERRUN goes away when I replaced 2nd !DATA_CNT_HIT by LOGIC_ONE:

2020-08-06_12-44-03.png

RD pulses count is 8192, but received data is still not valid, two words are missing as on the picture above (same offset 0x21FC).

Debug output:

Event: CY_U3P_USB_EVENT_VBUS_VALID

Event: CY_U3P_USB_EVENT_CONNECT

Initialization completed.

Event: CY_U3P_USB_EVENT_SET_SEL

Event: CY_U3P_USB_EVENT_SETCONF

Connected to Super-Speed host.

Unknown EP0 request received

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (0), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0) <<< Vendor command sent here

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (0)

glDmaRxCount (1), glDmaTxCount (1) <<< Data transferred to host

glDmaRxCount (1), glDmaTxCount (1)

glDmaRxCount (1), glDmaTxCount (1)

glDmaRxCount (1), glDmaTxCount (1)

glDmaRxCount (1), glDmaTxCount (1)

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

Hello,

I have tested the attached firmware at my end.

1) I have pulled up DQ[15] pin and then passed the vendor command. On transfer IN I don't see the data loss

2) For the second test,I have pulled up DQ[1] pin and then passed the vendor command. I don't see the data loss in this case as well

Here are the debug prints for the same

teraterm_prints.PNG

From this test, we can confirm that the problem is not on the FX3 hardware but it might be in the synchronization between FX3 (IN DATA) and FPGA (DATA_OUT).

There is a possibility that data is not in sync with the DATA IN of FX3.

To confirm that we would need the traces of data lines (16 bit) along with the RD signal. Please probe the data bus along with the RD signals and share the traces.

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

I already made a lot of experiments with different FPGA and logic analyzer. It seems my FX3 has a bug, so I ordered another board based on CYUSB3014. I'll compare both and hope second board will work correctly. I will post results later.

0 Likes