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.

Problem using QDMA to copy a buffer from IRAM to SDRAM

Hi

I am trying to use the QDMA on the c6713 to copy a small array from IRAM to SDRAM, but I cannot get it to work.

The reason I am using QDMA is that once my HW is ready the destination will be moved to an external memory address.

My source look like this


/*Global declaration of source and destination buffers*/
_NEAR Uint16 qdma_test_buffer_src[4] = {1, 2, 3, 4};  /* placed in IRAM */
Uint16 qdma_test_buffer_dst[4] = {0, 0, 0, 0};        /* placed in SDRAM */

/* EDMA_Config TestQDMA */
EDMA_Config TestQDMA = {
EDMA_OPT_RMK(
EDMA_OPT_PRI_HIGH,
EDMA_OPT_ESIZE_16BIT,
EDMA_OPT_2DS_NO, 
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO, 
EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_NO,
EDMA_OPT_TCC_OF(0),
EDMA_OPT_LINK_NO, 
EDMA_OPT_FS_NO 
),
EDMA_SRC_OF((Uint32) qdma_test_buffer_src),/* Source address register */
EDMA_CNT_OF(4), /* Transfer count parameter */
EDMA_DST_OF((Uint32) qdma_test_buffer_dst), /* Destination address parameter */
EDMA_IDX_OF(0x00000000), /* Index parameter */
EDMA_RLD_OF(0x00000000) /* Count reload/link parameter */
};

/*
* ======== cslCfgInit() ======== 
*/

void cslCfgInit()
{

  EDMA_qdmaConfig(&TestQDMA);

}

int main()
{
CSL_init();
cslCfgInit();
Framework_Init(ApplLibInit, FALSE, PROCESSOR_FDSP); /* start of DSPBIOS */ 
}

I have a breakpoint i main after I call cslCfgInit() and in the emulator I can see that qdma_test_buffer_dst is still zero.

In the Emulator I can see that the EDMA handle TestQDMA is setup with the right source, destination and count, and the option field is also as expected.

Does anybody know what I am doing wrong? 

Thanks

Jens Biltoft

  • Jens,

    Have you been able to get a CSL example for QDMA to work, without modification?

    Could you be having cache issues with observing the data in external memory?

    Regards,
    RandyP

  • Hi Randy

    I have not tried the CSL examples, because the source that I started out with worked perkectly. There I have two QDMAs running with almost the same setup, the only difference is that that the data is copied from IRAM to a FIFO implemented in an FPGA, which means that the Destination address is not incremented and that the data is written to an external address bus instead of SDRAM.

    Also the CSL example I have uses the EDMA instead of the QDMA.

    I do not know if there is a cache issue, how can I tell if there is? and what can I do about it?

    Regards 

    Jens

  • Jens,

    Just as a simple confirmation, please add a for (i=0;i<1000;i++); after the call to cslCfgInit(), then set your breakpoint after the for-loop. Does that change any behavior.

    Assuming that does not help, please show the setup for the QDMA operations in your source that your started out with, which worked perfectly. We can compare the two to try to find the cause.

    Also, please try initializing the SDRAM destination buffer with alternating patterns of 0xaaaaaaaa and 0x55555555.

    Regards,
    RandyP

  • Randy,

    It does not change anything if I add the delay you suggest, the destination array is not updated.

    In the code that worksthe QDMA is setup like this

    #define FPGA_GIDSP_HS_FIFO_ADDR (0xB0000000+ 0x26) // High Speed FIFO DSP <--> GIDSP

    _NEAR SHighSpeedFiFoGiDspOut stHighSpeedFiFoGiDspOut = {0}; //declare to GI-DSP fifo structure 10 elements

    EDMA_Config GIHighSpeedFiFoOutQDMA = {

    0x29000000, /* Option */
    (Uint32) &stHighSpeedFiFoGiDspOut, /* Source Address - From User's Header File */
    0x00000000, /* Transfer Counter - Numeric */
    (Uint32) FPGA_GIDSP_HS_FIFO_ADDR, /* Destination Address - From User's Header file */
    0x00000000, /* Index register - Numeric */
    0x00000000 /* Element Count Reload and Link Address */
    };

    in cslCfgInit() the Transfer Counter is set to 24 using this command

    GIHighSpeedFiFoInDMA.cnt = EDMA_CNT_RMK(0,sizeof(stHighSpeedFiFoGiDspIn)/sizeof(uint16));

    As I see it there are two differences between the two setups

    1 the destination adress is in external memory space

    2 the destination update mode is NONE instead of INC (because I write to a FIFO)

    I have tried changing the DUM to NONE to see if it was possible to only update one address in the destination buffer but that did not change anything.

    But if I move the destination buffer to IRAM then the QDMA is able to copy the data from source to desitnation!

    So it seems that the QDMA for some reason is not able to write to the SDRAM???

    Jens


  • Jens,

    Thank you for the reply back.

    Please try initializing the SDRAM destination buffer with alternating patterns of 0xaaaaaaaa and 0x55555555. I want to confirm that the SDRAM is configured and writable.

    If the only change from one test to the next is the destination buffer, changing from IRAM to SDRAM, then the QDMA would seem to be working and programmed correctly. The test above is the next thing to try.

    Can you test for completion of the QDMA, even if the data is not transferred? This would confirm that the QDMA is trying to do the copy even though you do not observe the data landing.

    Regards,
    RandyP

  • Randy,

    I already tried initalizing the SDRAM with Uint16 qdma_test_buffer_dst[4] = {0x5555, 0xaaaa, 0x5555, 0xaaaa};

    And I can see in the debugger that it is initialized as expected.

    If I change the setup of the QDMA to generate TransferCompleteInterrupt then I can see that the CIPR register changes from 0x00000000 to 0x00000001 right after I have trigged the QDMA. So it seems that the QDMA tries to do the copy.

    Jens

  • Jens,

    One quick thought between meetings: Can you change the priority or Queue of the QDMA transfer to see if that affects the outcome?

    Regards,
    RandyP

  • Randy,

    Changing the priority to LOW did not change anything.

    Is there more than one queue for the QDMA?

    Jens

  • Jens,

    In your code, clear MAR0 by writing 0 to 0x01848200 early in main(). Please let me know how that works.

    The rest of this is what I wrote first, still trying to debug the code and not the system. So I will leave it in the post, although cache coherency can easily be the issue. This should have shown up with a clue in the Memory Browser window, although I am not sure if the cache highlighting works for the C6713.

    Since you are not using the exact same code that worked before, but using a different syntax for setting everything up, it seems likely that something subtle has changed.

    My [other] recommendations today are:

    1. Try one of the DAT_copy examples from the CSL to see if you can get that to work.

    2. Write the function in C to have the DSP copy the 4 half-words from IRAM to SDRAM.

    3. Copy your FIFO code exactly and use it with the SDRAM destination address. Even though the destination location will not change, at least one half-word should change.

    4. Reply back with that the 5 QDMA register contents are from a memory browser window, after doing the transfer attempt.

    5. Write the QDMA registers directly in your code. Write to four of the QDMA registers, then write the fifth value to the Pseudo register equivalent of that fifth register.

    If none of this helps to reach a solution, then the next step will be to start over at the top of this thread and retry all the things we have talked about. Capture screen shots that show the results instead of simple confirmation. There must be something missing that we have not communicated, yet.

    Regards,
    RandyP

  • Randy,

    If I clear MAR0, the QDMA works perfectly, and I can copy data from IRAM to SDRAM.

    Can you explain what MAR0 is?

    Jens

  • Jens,

    The QDMA module is outside of the DSP core, so it works directly with the SDRAM and with any other memory components. The DSP core has its own internal cache that it uses to save information for quicker access later. The DSP cache and the QDMA are not aware of each other and work independently, so if some data is read from the SDRAM by the DSP and at the same time that data is saved into the DSP cache, the DSP will think it has the latest copy of the data in its cache. When the QDMA writes to that SDRAM location with new data, the DSP does not know that so the DSP will not go out to the SDRAM to get the new data, but will read from its internal cache instead.

    The MAR bits turn off the caching mechanism for a region of memory. This is not always the best way to solve this problem, but it is one quick way to locate the problem, which you have done now. Turning off the cache removes the performance improvements that caching brings, so it will be best to find another way to solve the problem.

    The Two Level Internal Memory Reference Guide has the best descriptions of the cache and the registers that control it, including the MAR bits.

    In the TI Wiki Pages, you can search for "c6713 workshop" (no quotes) and find an archived training class on the C6000 architecture specifically for the devices C6416 and C6713. There is a module in that training about cache and the tools you can use with the cache to improve performance. The entire workshop will be worthwhile for you to go through to learn things about the DSP and the architecture and the tools, although it is based on the old and unsupported CCS 3.x.

    Regards,
    RandyP