This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C6678 PCIe throughput

Hello All,

I have a C6678 configured as (RC) and interfaces with Spartan6 (EP). PCIe code based on the "pcie_sample" code in the pdk. I can successfully issue a memory read from the RC to the EP.

I have the EP interrupts the RC using a GPIO whenever the EP has a block of 3072 int (32-bit). The RC then issues a memory read to read the block from the FPGA Simple Dual Port RAM. The GPIO interrupt occurs every 6 ms and I thought the time it takes to read from the EP is very small as follows:

Payload = 4 bytes (SPARTAN6 supports 32-bit read only)
Header = 16 bytes
ECRC   = 4 bytes
Link   = 8 bytes
Percent Throughput - 4/44 = 9%

Max. Effective Throughput = 2.5 Gbps x 1 lane
= 2.5 Gbps x 8/10 (encoding)
= 2 Gbps
= 2000 Mbps

at 9%
= 2000 Mbps * 9/100
= 180 Mbps

180000000 bits     <-------------> 1 sec
3072*32 bits       <-------------> 546 microsec

My GPIO_ISR does the following to read the block of data:

rdPtr = (int *)&algInputBuff[0];

for (k = 0; k < (3072); k++)

*rdPtr++ = *((volatile uint32_t *)pcieDataBase + k);//3072 32-bit samples

Also, I kept the translation as in the example code.

The PROBLEM is that my ISR takes more time to process the block of samples than the 6 ms so I miss further gpio interrupts. When I change the code to read the same data from a dsp buffer, the ISR runs fast enough and no missing interrupts occur

I am planning to use EDMA, but I never used DMA before and I need sometime to do that...but what am I doing wrong... can I change the outbound translation to speed up the transfer before employing EDMA?

 

Regards,

 

Murad

 

  • Hi Murad,

    it takes much longer to read a word over PCIe because the DSP first sends a read request packet to the FPGA and then it has to wait for the result to come in. The whole process can take microseconds.
    It should be possible to reduce the overhead by increasing the payload size using EDMA.

    Ralf
  • Murad,

    I am not the expert for PCIe, but the PCIe expert can be clarified for your PCIe related query.

    Murad: said:
    I am planning to use EDMA, but I never used DMA before and I need sometime to do that...but what am I doing wrong... can I change the outbound translation to speed up the transfer before employing EDMA?


    Here, you can find the CSL based edma test code at the PDK: C:\ti\pdk_C6678_1_1_2_6\packages\ti\csl\example\edma
    You can take this as reference code and implement on the PCIe application.

     

  • Thanks Ralf and Pubesh for your reply,
    I am studying the code you mentioned above Pubesh but I was hoping for a way to speed the PCIe outbound read without DMA. Also, if my calculations are ok above, 6 ms should be plenty of time to transfer 3072 int!!!???...is there a way to use the outbound translation to read into L2/L1 memory since PCIe is a bus master?...again, I am using the example code translation as is
  • Hi Murad,

    Better to increase the payload size and use the EDMA for PCIe transfer test code.

    EDMA base PCIe test code is available in MCSDK package. Please take a look at section in test code.

    MCSDK Path: \ti\mcsdk_2_01_02_06\tools\boot_loader\examples\pcie\linux_host_loader\pciedemo.c

    Refer readme(C:\ti\mcsdk_2_01_02_06\tools\boot_loader\examples\pcie\docs\) document for more information.

    Thanks,

  • Thank you Ganapathi,
    I looked at the above code but it doesn't show how to setup the C6678 for EDMA...it setup the Linux DMA...correct. I am reading more about the EDMA and will do some timing measurement of the PCIe outbound memory read to compare with theoretical values...all theory timing are showing that it takes less than 1 ms to read 3072 int (32-bit) using gen 1 x1 PCIe!


    Regards,

    Murad
  • Hi guys,
    Is this is the correct settings for the EDMA, specially the aCnt, cBnt to read 3072 int (12288 bytes) from FPGA using PCIe?.
    // Setup the first param Entry (Ping buffer)
    myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_DIS,\
    0,CSL_EDMA3_TCC_NORMAL,\
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_DIS, \
    CSL_EDMA3_SYNC_A, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR);
    myParamSetup.srcAddr = (Uint32)0x60000000;
    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(12288,1);
    myParamSetup.dstAddr = (Uint32)destAddr;
    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(1,1);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk1,0);
    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,1);
    myParamSetup.cCnt = 1;

    PCIe user's guide talks about PCIe max payload and sets the aCnt, bCnt differently
    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(128, 12288/128);


    Also, how do I make sure I am using CC0 which has 256 bit access bus as described in SPRABK5A?


    Regards,

    Murad
  • Can someone help please!

    My code works fine when I use the CPU to read FPGA memory (3072 integers) using PCIe inside a timer interrupt as follows:

    rdPtr = (int *)&algInputBuff[0];

    for (k = 0; k < (3072); k++)

    *rdPtr++ = *((volatile uint32_t *)pcieDataBase + PCIe_SDPRAM_block_count*(3072) + k);//3072 32-bit samples

    BUT when I use the EDMA3, I get nothing!!!???...my code is shown below (not sure how to attach to this post). I have 4 blocks inside the FPGA SDPRAM, each block is 3072 integers and I am using linked EDMA PaRAM.

    the folloing are defined in my edma.h

    /* Define payload size and buffer size */

    #define PCIe_MAX_PAYLOAD   (128)   // Assume pcie maximum payload size is 128 bytes

    #define FPGA_DATA_BLOCK_SIZE_BYTES (3072) // 3072-32-bit (16 bits I and 16 bits Q)

    // Define PCIe data starting address for EDMA transfer

    #define PCIe_DATA_ADDR (0x60000000)

    edma.c

    #include "edma3.h"

    extern uint32_t pcieConvert_CoreLocal2GlobalAddr (uint32_t addr);

    CSL_Edma3ChannelHandle hChannel;

    int cfg_edma3_INPUT(int *destAddr)

    {

    CSL_Edma3Handle hModule;

    CSL_Edma3ParamHandle hEdma_blk0;

    CSL_Edma3ParamHandle hEdma_blk1;

    CSL_Edma3ParamHandle hEdma_blk2;

    CSL_Edma3ParamHandle hEdma_blk3;

    CSL_Edma3Obj edmaObj;

    CSL_Edma3ChannelObj chObj;

    //CSL_Edma3ChannelHandle hChannel;

    CSL_Edma3ChannelAttr chAttr;

    CSL_Edma3Context context;

    CSL_Status status;

    CSL_Edma3ParamSetup myParamSetup;

    Uint8 instNum = 2;

    Uint8 channelNum = 0;

    Uint8 paRAM_number = 0;

    // Initialize the EDMA3 Module.

    if (CSL_edma3Init(&context) != CSL_SOK)

    {

    platform_write ("Error: EDMA module initialization failed\n");

    return -1;

    }

    // Open the EDMA Module using the provided instance number

    hModule = CSL_edma3Open(&edmaObj,instNum,NULL,&status);

    if ( (hModule == NULL) || (status != CSL_SOK))

    {

    platform_write ("Error: EDMA module open failed\n");

    return -1;

    }

    // Open DMA Channel "channelNum".

    chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;

    chAttr.chaNum = channelNum;

    hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);

    if ((hChannel == NULL) || (status != CSL_SOK))

    {

    platform_write("Error: Unable to open EDMA Channel:%d\n", chAttr.chaNum);

    return -1;

    }

    // /* For first EDMA instance there are only 2 TCs and 2 event queues

    // * Modify the channel default queue setup from 0 to 0?

    // */

    // if (CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_0) != CSL_SOK)

    // {

    // platform_write ("Error: EDMA channel setup queue failed\n");

    // return -1;

    // }

    /* Map the DMA Channel to PARAM Block 0. */

    CSL_edma3MapDMAChannelToParamBlock(hModule, channelNum, 0);//MQ: ??

    // CSL_edma3HwChannelSetupParam(hChannel, paRAM_number);

     

    // Obtain a handle to PARAM Entry 0

    hEdma_blk0 = CSL_edma3GetParamHandle(hChannel,0,&status);

    if (hEdma_blk0 == NULL)

    {

    platform_write ("Error: EDMA Get Parameter Entry failed for 0.\n");

    return -1;

    }

    // Obtain a handle to PARAM Entry 1

    hEdma_blk1 = CSL_edma3GetParamHandle(hChannel,1,&status);

    if (hEdma_blk1 == NULL)

    {

    platform_write ("Error: EDMA Get Parameter Entry failed for 1.\n");

    return -1;

    }

    // Obtain a handle to PARAM Entry 2

    hEdma_blk2 = CSL_edma3GetParamHandle(hChannel,2,&status);

    if (hEdma_blk2 == NULL)

    {

    platform_write ("Error: EDMA Get Parameter Entry failed for 2.\n");

    return -1;

    }

    // Obtain a handle to PARAM Entry 3

    hEdma_blk3 = CSL_edma3GetParamHandle(hChannel,3,&status);

    if (hEdma_blk3 == NULL)

    {

    platform_write ("Error: EDMA Get Parameter Entry failed for 3.\n");

    return -1;

    }

    ////////////////////// Setup the first param Entry (Ping buffer) //////////////////////

    myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \

    CSL_EDMA3_TCCH_DIS, \

    CSL_EDMA3_ITCINT_DIS, \

    CSL_EDMA3_TCINT_DIS,\

    0,CSL_EDMA3_TCC_NORMAL,\

    CSL_EDMA3_FIFOWIDTH_NONE, \

    CSL_EDMA3_STATIC_DIS, \

    CSL_EDMA3_SYNC_AB, \

    CSL_EDMA3_ADDRMODE_INCR, \

    CSL_EDMA3_ADDRMODE_INCR);

    myParamSetup.srcAddr = (Uint32)PCIe_DATA_ADDR;

    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(PCIe_MAX_PAYLOAD,4*FPGA_DATA_BLOCK_SIZE_BYTES/PCIe_MAX_PAYLOAD);

    myParamSetup.dstAddr = (uint32_t)pcieConvert_CoreLocal2GlobalAddr ((uint32_t)destAddr);

    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(PCIe_MAX_PAYLOAD,PCIe_MAX_PAYLOAD);

    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk1,0);

    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);//MQ: was (0,1)

    myParamSetup.cCnt = 1;

    // Configure the PARAM Entry with the setup information.

    if (CSL_edma3ParamSetup(hEdma_blk0,&myParamSetup) != CSL_SOK)

    {

    platform_write ("Error: EDMA Parameter Entry 0 Setup failed\n");

    return -1;

    }

    ////////////////////// now set up ping block 1 //////////////////////

    myParamSetup.srcAddr = (unsigned int)(PCIe_DATA_ADDR + FPGA_DATA_BLOCK_SIZE_BYTES);

    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk2,0);

    // Configure the PARAM Entry with the setup information.

    if (CSL_edma3ParamSetup(hEdma_blk1,&myParamSetup) != CSL_SOK)

    {

    platform_write ("Error: EDMA Parameter Entry 1 Setup failed\n");

    return -1;

    }

    ////////////////////// now set up pong block 2 //////////////////////

    myParamSetup.srcAddr = (unsigned int)(PCIe_DATA_ADDR + 2*FPGA_DATA_BLOCK_SIZE_BYTES);

    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk3,0);

    // Configure the PARAM Entry with the setup information.

    if (CSL_edma3ParamSetup(hEdma_blk2,&myParamSetup) != CSL_SOK)

    {

    platform_write ("Error: EDMA Parameter Entry 2 Setup failed\n");

    return -1;

    }

    ////////////////////// now set up ping block 3 //////////////////////

    myParamSetup.srcAddr = (unsigned int)(PCIe_DATA_ADDR + 3*FPGA_DATA_BLOCK_SIZE_BYTES);

    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk0,0);

    // Configure the PARAM Entry with the setup information.

    if (CSL_edma3ParamSetup(hEdma_blk3,&myParamSetup) != CSL_SOK)

    {

    platform_write ("Error: EDMA Parameter Entry 3 Setup failed\n");

    return -1;

    }

    // Enable Channel

    if (CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL) != CSL_SOK)

    {

    platform_write ("Error: EDMA Channel Enable failed\n");

    return -1;

    }

    return(0);

    } /* end cfg_edma */

    Regards,

    Murad

  • Updates:
    1- I am triggering the EDMA from another file using:
    //Trigger channel
    CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);

    and noticed that the channel configurations got changed when I leave the edma.c file. To fix this, I declared all the variables as global and EDMA worked fine WITH having the "source address" point to a local buffer!
    Q1: why do I have to declare the channel variables global. when I only declared the "hChannel" as global, channel config got corrupted????
    Q2: Why do I have to add another parameter handle (hEdma_init) so that the last parameter handle is NOT linked to it instead of the second parameter handle (hEdma_blk0) ????
    2- I verified that the EDMA3 is working OK by assigning the source address to a local buffer inside the DSP.
    3- I verified that the RC(C6678) PCIe interface with EP (FPGA) is working OK by reading a pre-initialized DPRAM inside the FPGA using:

    rdPtr = (int *)&algInputBuff[0];
    for (k = 0; k < (3072); k++)
    *rdPtr++ = *((volatile uint32_t *)pcieDataBase + PCIe_SDPRAM_block_count*(3072) + k);//3072 32-bit samples

    where pcieDataBase is defined as:
    volatile UInt32 *pcieDataBase = (UInt32 *)0x60000000;

    4- When I changed the EDMA3 source address to point to the PCIe Data Space (0x60000000), I COULDN'T read the FPGA DPRAM data??????.

    My latest EDMA code is:

    edma3.h

    /* Define payload size and buffer size */
    #define PCIe_MAX_PAYLOAD (128) // Assume pcie maximum payload size is 128 bytes
    #define FPGA_DATA_BLOCK_SIZE_BYTES (3072) // 3072-32-bit (16 bits I and 16 bits Q)

    // Define PCIe data starting address for EDMA transfer
    #define PCIe_DATA_ADDR (0x60000000)


    edma3.c


    #include "edma3.h"
    extern uint32_t pcieConvert_CoreLocal2GlobalAddr (uint32_t addr);

    CSL_Edma3ChannelHandle hChannel;
    CSL_Edma3Handle hModule;
    CSL_Edma3ParamHandle hEdma_init;
    CSL_Edma3ParamHandle hEdma_blk0;
    CSL_Edma3ParamHandle hEdma_blk1;
    CSL_Edma3ParamHandle hEdma_blk2;
    CSL_Edma3ParamHandle hEdma_blk3;

    CSL_Edma3Obj edmaObj;
    CSL_Edma3ChannelObj chObj;
    CSL_Edma3ChannelAttr chAttr;
    CSL_Edma3Context context;
    CSL_Status status;

    CSL_Edma3ParamSetup myParamSetup;

    Uint8 instNum = 1;
    Uint8 channelNum = 10;
    Uint8 paRAM_number = 0;

    int CFG_edma3_INPUT(int *destAddr)
    {
    // Initialize the EDMA3 Module.
    if (CSL_edma3Init(&context) != CSL_SOK)
    {
    platform_write ("Error: EDMA module initialization failed\n");
    return -1;
    }

    // Open the EDMA Module using the provided instance number
    hModule = CSL_edma3Open(&edmaObj,instNum,NULL,&status);
    if ( (hModule == NULL) || (status != CSL_SOK))
    {
    platform_write ("Error: EDMA module open failed\n");
    return -1;
    }

    // Open DMA Channel "channelNum".
    chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
    chAttr.chaNum = channelNum;
    hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);
    if ((hChannel == NULL) || (status != CSL_SOK))
    {
    platform_write("Error: Unable to open EDMA Channel:%d\n", chAttr.chaNum);
    return -1;
    }

    // /* For first EDMA instance there are only 2 TCs and 2 event queues
    // * Modify the channel default queue setup from 0 to 0?
    // */
    if (CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_0) != CSL_SOK)
    {
    platform_write ("Error: EDMA channel setup queue failed\n");
    return -1;
    }

    /* Map the DMA Channel to PARAM Block 0. */
    CSL_edma3MapDMAChannelToParamBlock(hModule, channelNum, 0);//MQ: ??
    CSL_edma3HwChannelSetupParam(hChannel, paRAM_number);

    // Obtain a handle to PARAM init Entry
    hEdma_init = CSL_edma3GetParamHandle(hChannel,0,&status);
    if (hEdma_init == NULL)
    {
    platform_write ("Error: EDMA Get Parameter Entry failed for 0.\n");
    return -1;
    }

    // Obtain a handle to PARAM Entry 0
    hEdma_blk0 = CSL_edma3GetParamHandle(hChannel,1,&status);
    if (hEdma_blk0 == NULL)
    {
    platform_write ("Error: EDMA Get Parameter Entry failed for 0.\n");
    return -1;
    }

    // Obtain a handle to PARAM Entry 1
    hEdma_blk1 = CSL_edma3GetParamHandle(hChannel,2,&status);
    if (hEdma_blk1 == NULL)
    {
    platform_write ("Error: EDMA Get Parameter Entry failed for 1.\n");
    return -1;
    }
    // Obtain a handle to PARAM Entry 2
    hEdma_blk2 = CSL_edma3GetParamHandle(hChannel,3,&status);
    if (hEdma_blk2 == NULL)
    {
    platform_write ("Error: EDMA Get Parameter Entry failed for 2.\n");
    return -1;
    }
    // Obtain a handle to PARAM Entry 3
    hEdma_blk3 = CSL_edma3GetParamHandle(hChannel,4,&status);
    if (hEdma_blk3 == NULL)
    {
    platform_write ("Error: EDMA Get Parameter Entry failed for 3.\n");
    return -1;
    }
    ////////////////////// Setup the first param Entry (Ping buffer) //////////////////////
    myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_DIS,\
    0,CSL_EDMA3_TCC_NORMAL,\
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_DIS, \
    CSL_EDMA3_SYNC_AB, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR);
    myParamSetup.srcAddr = (Uint32)PCIe_DATA_ADDR;
    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(PCIe_MAX_PAYLOAD,4*FPGA_DATA_BLOCK_SIZE_BYTES/PCIe_MAX_PAYLOAD);//32 bits = 4 bytes
    myParamSetup.dstAddr = (uint32_t)pcieConvert_CoreLocal2GlobalAddr ((uint32_t)destAddr);
    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(PCIe_MAX_PAYLOAD,PCIe_MAX_PAYLOAD);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk0,4*FPGA_DATA_BLOCK_SIZE_BYTES/PCIe_MAX_PAYLOAD);
    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);//MQ: was (0,1)
    myParamSetup.cCnt = 1;

    // Configure the PARAM init Entry with the setup information.
    if (CSL_edma3ParamSetup(hEdma_init,&myParamSetup) != CSL_SOK)
    {
    platform_write ("Error: EDMA Parameter Entry 0 Setup failed\n");
    return -1;
    }

    ////////////////////// now set up ping block 0 //////////////////////
    myParamSetup.srcAddr = (Uint32)(PCIe_DATA_ADDR);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk1,0);

    // Configure the PARAM Entry with the setup information.
    if (CSL_edma3ParamSetup(hEdma_blk0,&myParamSetup) != CSL_SOK)
    {
    platform_write ("Error: EDMA Parameter Entry 0 Setup failed\n");
    return -1;
    }

    ////////////////////// now set up ping block 1 //////////////////////
    myParamSetup.srcAddr = (Uint32)(PCIe_DATA_ADDR + FPGA_DATA_BLOCK_SIZE_BYTES);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk2,0);

    // Configure the PARAM Entry with the setup information.
    if (CSL_edma3ParamSetup(hEdma_blk1,&myParamSetup) != CSL_SOK)
    {
    platform_write ("Error: EDMA Parameter Entry 1 Setup failed\n");
    return -1;
    }

    ////////////////////// now set up pong block 2 //////////////////////
    myParamSetup.srcAddr = (Uint32)(PCIe_DATA_ADDR + 2*FPGA_DATA_BLOCK_SIZE_BYTES);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk3,0);

    // Configure the PARAM Entry with the setup information.
    if (CSL_edma3ParamSetup(hEdma_blk2,&myParamSetup) != CSL_SOK)
    {
    platform_write ("Error: EDMA Parameter Entry 2 Setup failed\n");
    return -1;
    }

    ////////////////////// now set up ping block 3 //////////////////////
    myParamSetup.srcAddr = (Uint32)(PCIe_DATA_ADDR + 3*FPGA_DATA_BLOCK_SIZE_BYTES);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hEdma_blk0,0);

    // Configure the PARAM Entry with the setup information.
    if (CSL_edma3ParamSetup(hEdma_blk3,&myParamSetup) != CSL_SOK)
    {
    platform_write ("Error: EDMA Parameter Entry 3 Setup failed\n");
    return -1;
    }


    // Enable Channel
    if (CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL) != CSL_SOK)
    {
    platform_write ("Error: EDMA Channel Enable failed\n");
    return -1;
    }

    return(0);
    } /* end cfg_edma */
  • More frustration results!!!!

    I have an array with initialized value located at address 0x81637120 (DDR3)
    when I changed the EDMA3 source address to the buffer location, EDMA3 works fine!!!!
    #define PCIe_DATA_ADDR 0x81637120//(0x60000000)
    But when I have it as 0x60000000, I get zeros....When I enter this address in the CCS "Memory Browser", I get the correct data from the EP (FPGA)!!!!!!!!!!!!!!!!!!!!!!!!!!!?????????????????????????
  • When you use CCS "Memory Browser" to read data from 0x60000000, the debugger reads data using DSP core on 4 bytes.

    It's the same thing that your code for the DSP core :

    rdPtr = (int *)&algInputBuff[0];
    for (k = 0; k < (3072); k++)
    *rdPtr++ = *((volatile uint32_t *)pcieDataBase + PCIe_SDPRAM_block_count*(3072) + k);//3072 32-bit samples

  • Correct Dmitry,
    So how come EDMA3 fails to do the same but can read internal source address and ddr3 address space but not 0x60000000?
  • Maybe you have a compatibility problem the Payload Size in TLP packets between two devices during the read?
    Check the reading of data from the FPGA via EDMA3 setting PCIe_MAX_PAYLOAD in value 4.
    The idea is to check, read data via PCIe using the TLP requests are 4 bytes, rather than 128.
    When your code works without EDMA3, requests to read data are 4 bytes.
    When your code works with EDMA3, read requests for data are 128 bytes.
  • Dear Dmitry,
    I thought the same.
    - I changed the max payload size on the DSP size to 4 which affects the aCnt but nothing changed.
    - The PCIe core on the FPGA allows to select the max payload size using a GUI and it is been set to 512 bytes. C6678 EDMA3 supports 128/64 bytes. I am expecting the payload size to affect speed performance, but not to get nothing from the EP!?. -Also, the FPGA PCIE for Spartan6 is v1.1 while C6678 PCIe is 2.0...do you think this can cause a problem with the EDMA3?
    -CPU access to PCIe is working without any problem. My second question, Can I have the EP (FPGA) initiate outbound memory write which is Inbound memory write to the C6678 and hence no need for EDMA/CPU (SPRABK8.pdf):
    "Inbound transfer means the external device initiates the transactions to write to or read
    from the local device. The PCIe module has a master port to transfer the data to or from
    the device memory; no CPU or EDMA is needed for inbound transfer in the local
    device."

  • You're right Murad.
    The EDMA3 can only work with data burst size (DBS) of 64 or 128 bytes. The value 4 not be able to use (I had not thought about it. Sorry.).

    I do not think you have a problem versions of PCIe, as the DSP core can read data from the FPGA.

    Change the logic of your test. Check the writing data using EDMA3.
    Create an array of data in the local memory of DSP, it must initialize the values and move it using EDMA3 in FPGA. 
    Then read the same data from the FPGA memory using the core DSP (without EDMA3).
    These look like?

    If you want to write data from the FPGA to the DSP memory , you must use the IP-core of CDMA in hardware platform for FPGA. The CDMA can manage from the DSP, mapped CDMA registers control with BAR-0 on the FPGA.

  • Hello Murad,

    You are using a hardware platform for FPGA, which can only work with single DWORD payload  ( DWORD in PCI-Express - 4 bytes).

    The EDMA3 at DSP will not work.
    You need a different hardware platform for FPGA.

    Look up page 129 in this document:

    http://www.xilinx.com/support/documentation/user_guides/s6_pcie_ug654.pdf

    You see:

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

    Supports single DWORD payload Read and Write PCI Express transactions to 32/64-bit address memory spaces and I/O space with support for completion TLPs

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

    Regards,

    Dmitry.

  • Thank you Dmitry for all your help!
    This is really bad news!!!. I thought that EDMA3 will only be slower!!!...I am using the Xilinx PEIe example with some changes to the memory read part. How to get a "different Hardware Platform"?. Do I need to change the xilinx example code to support higher payload...I thought the single DWORD payload is only a PIO limitations, not a PCIe core limitations especially you can select 128/256/512 bytes when you generate the PCIe Core...Unfortunately, I don't have much experience with FPGAs. I will try DSP Cache and maybe use core 0 of the C6678 to just read the FPGA data...This is delaying my project big time!

    Best Regards,

    Murad
  • Hello Murad,

    may still have a chance to use the EDMA3 ......

    The EDMA3 can operate in two modes of "synchronization event" - "non-bursting" and "bursting".
    Read the section "3.4 Peripheral Servicing Example" on page 86 of this document:
    http://www.ti.com/lit/ug/sprugs5a/sprugs5a.pdf

    You can try to use "non-bursting".

    The EDMA3 channel number 12 (Receive Chunnel) to read data from the FPGA, channel Number 13 (Transmit Channel) to write data to FPGA (see section 3.4.3.1 and 3.4.3.2 of sprugs5a.pdf).

    The chance that EDMA3 can be used in the mode of "non-bursting" with PCIe indirectly confirmed by the section "2.10.1.3 Burst Type Reguerements" of document http://www.ti.com/lit/ug/sprugs6d/sprugs6d.pdf. You see:

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

    The PCIESS does not support fixed or wrap burst types.

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

    I think that can happen to use EDMA3, but the speed in "non-bursting" is low.

    Regards,

    Dmitry.

  • Dmitry,
    Thank you so very much for all your help. Channel 13 was the answer...combined with 3.4.5.2 Breaking Up Large Transfers with Intermediate Chaining, I was able to move a block of 3072 with one trigger from the DSP. Again, I appreciate all your support...Happy Holidays!

    Regards,

    Murad