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.

Use EDMA3 to Set up a Transfer without using edma3 LLD

Other Parts Discussed in Thread: TMS320C6747

Hi,

    I want to use EDMA to set up a transfer without using edma3 lld and get rid of bios because of a matter of code size.Can you give me some code examples or specific steps to set up a transfer

  • Jia Tang,

    It could be helpful to know which DSP you are using. For some DSPs, we offer Chip Support Library (CSL) in functional-layer or register-layer forms.

    By default, DSP/BIOS is configured with all features enabled. You can reduce the program and data space usage significantly by manually disabling features of DSP/BIOS that you do not need, such as instrumentation or MBX. An old application note showed that a default configuration might use 23KB program and 9KB data, while a minimized configuration might use 3KB program and 1.3KB data; this was for an older version of DSP/BIOS, but it illustrates that substantial code size reduction is possible.

    So if your primary reason for avoiding DSP/BIOS is memory size, you may want to make some new tradeoff analysis to see if the convenience of DSP/BIOS can work for you with a smaller size.

    Please search the TI Wiki Pages for articles about EDMA3 programming. There is an article that deals with direct-register programming for a specific device, here. Take notice, please, that this programming technique assumes a complete understanding of the EDMA3 architecture, and this technique does not always migrate perfectly to other DSPs because of slight variations in the EDMA3 implementations. These variations are handled for you in functional-layer CSL or the EDMA3 LLD for a specific device.

    We provide the EDMA3 User's Guide for each device, with details on the inner workings of the EDMA3 module plus programming model descriptions (in some cases). And we provide the EDMA3 LLD to abstract that detail for you into a tested and practical programming environment.

    I strongly recommend that you reconsider your decision to avoid the EDMA3 LLD programming model. At the very least, consider using DSP/BIOS and EDMA3 LLD for developing your code, and then reduce it as needed to meet your application's requirements. In this way, you will have a working example to compare with when your direct-register EDMA3 programming model runs into trouble.

    Since a DSP/BIOS application must return from main() to start the DSP/BIOS scheduler, and since a non-DSP/BIOS application stays in main() forever, you can make simple changes to allow a non-DSP/BIOS application to be run under DSP/BIOS without very much impact to your program. Here are some steps that will help you convert from a non-DSP/BIOS application (if you have already written it that way) to a DSP/BIOS application with minimum use of DSP/BIOS features. These steps have not been tested, but I wanted to make these suggestions as a starting point for you.

    1. Remove your "vectors.asm" or similar file for implementing the interrupt vector table. This will be created by DSP/BIOS.
    2. For each Interrupt Service Routine (ISR), you are probably using the "interrupt" keyword. To retain that method, just write the name of each ISR in the proper HWI_n setup box, leaving Use Dispatcher unchecked. Remember to prepend "_" in front of the C function name.
    3. Divide your main() function into system initialization functions (like enabling specific interrupts and peripherals) and operation code. Leave the init portion in main() and move the operation code to MainTask().
    4. Add a single task in the DSP/BIOS configuration and give it the function _MainTask.

    I may have left off a step or two, but this is the basic set of requirements to work with DSP/BIOS with minimal overhead.

    Regards,
    RandyP

  • RandyP,

    Thank you very much for your explanation in such detail.

    I am using TMS320C6747.I have tried the article in TI Wiki pages as you mentioned,but it didn't work.

    I also want to use DSP/BIOS and EDMA3 LLD,but my boss don't agree me do it in that way.Because we plan to only do memory-to-memory transfers using the DMA or even Quick DMA (QDMA), similar to a memcpy() in C,but ACPY3 API library must via a framework like CE.So,I want you can give a simple example like the article in TI Wiki pages based on tms320c6747.And I appreciate your helping me!

  • Jia Tang,

    You might be able to find some useful information in test files supplied with the EVM from Spectrum Digital.

    However, the example files that come with the TI PSP software use the EDMA3 LLD code. That is the way we support the EDMA3 programming for the C6747.

    If you are going to program at the register level, you will have to debug at the register level. But as a starting point, I recommend building a working example using DSP/BIOS and the EDMA3 LLD. Then you could try the following, with 1 being the easiest and 3 being the most robust solution:

    1. Capture the state of all the EDMA3CC and EDMA3TC registers and compare them to the register values from your failing register-level example.

    2. Examine the EDMA3 LLD source files and determine which registers were written that your register-level example did not write.

    3. Figure out a way to modify the EDMA3 LLD so it does not require DSP/BIOS.

    Regards,
    RandyP

  • RandyP,

    where to download the useful information in test files supplied with the EVM from Spectrum Digital?

  • RandyP,

    I have download the test files at the http://support.spectrumdigital.com/boards/evmc6747/revb/  .But it doesn't have the infomation and example of EDMA3.Can you give me another way to find example for using edma3 at the register level. Thank you!

     

  • Jia Tang,

    Those were the best chances that I know of. The steps I listed above, comparing and/or using parts of the EDMA3 LLD will be your best change for success now.

    When you tried the example from the Wiki, did you make any changes to the code to adapt it to the C6747? For example, did register base addresses change or EDMA3 features change? To determine this, you need to read the C6747 datasheet and find the base address of the EDMA3CC registers. Have you found this? If it is different from what is in the example code from the Wiki, you will need to change it to match your DSP.

    Look through the registers that are defined and written in the Wiki example. Do all of them exist in the C6747 datasheet? If not, then there are architectural changes that you may need to be aware of. This can be learned by reading the EDMA3 User's Guide, or at least by searching the DM648 EDMA3 UG for those registers and then comparing that section with the same one in the C6747 EDMA3 UG.

    When you said "it didn't work", what exactly does that mean?
    Did you look at the EDMA3 registers in a memory window to see how they were being modified?
    What debug steps did you take to see how it was failing?

    RandyP

     

    If this answers your question, please click the  Verify Answer  button below. If not, please reply back with more information.

  • RandyP

    Here are the code example for DM648 platform

    /************************************************************************************/

    /* EDMA register address and definitions */

    #define EDMA_CC_BASE (0x02A00000) /* DM648. Check address for other devices. */
    #define DCHMAP0 *((volatile unsigned int *)(EDMA_CC_BASE + 0x0100))
    #define DMAQNUM0 *((volatile unsigned int *)(EDMA_CC_BASE + 0x0240))
    #define QUEPRI *((volatile unsigned int *)(EDMA_CC_BASE + 0x0284))
    #define EMCR *((volatile unsigned int *)(EDMA_CC_BASE + 0x0308))
    #define EMCRH *((volatile unsigned int *)(EDMA_CC_BASE + 0x030C))
    #define QEMCR *((volatile unsigned int *)(EDMA_CC_BASE + 0x0314))
    #define CCERRCLR *((volatile unsigned int *)(EDMA_CC_BASE + 0x031C))
    #define QWMTHRA *((volatile unsigned int *)(EDMA_CC_BASE + 0x0620))
    #define ESR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1010))
    #define IPR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1068))
    #define ICR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1070))

    #define PARAMENTRY0 (0x02A04000) /* DM648. Check address for other devices. */
    #define OPT *((volatile unsigned int *)(PARAMENTRY0 + 0x00))
    #define SRC *((volatile unsigned int *)(PARAMENTRY0 + 0x04))
    #define A_B_CNT *((volatile unsigned int *)(PARAMENTRY0 + 0x08))
    #define DST *((volatile unsigned int *)(PARAMENTRY0 + 0x0C))
    #define SRC_DST_BIDX *((volatile unsigned int *)(PARAMENTRY0 + 0x10))
    #define LINK_BCNTRLD *((volatile unsigned int *)(PARAMENTRY0 + 0x14))
    #define SRC_DST_CIDX *((volatile unsigned int *)(PARAMENTRY0 + 0x18))
    #define CCNT *((volatile unsigned int *)(PARAMENTRY0 + 0x1C))

    /* Allocate srcBuff and dstBuff. Do a cache flush and cache invalidate,if required. */
    static signed char srcBuff[512];
    static signed char dstBuff[512];

    /* Step 1: EDMA initialization */
    QUEPRI=0x10;
    QWMTHRA =(16<<8u)|(16 & 0xFF);
    EMCR = 0xFFFFFFFF;
    CCERRCLR = 0xFFFFFFFF;

    /* Step 2: Programming DMA Channel (and Param set) */
    DCHMAP0=0x0;
    DMAQNUM0=0x0;
    OPT = 0x00100000; /* only TCINTEN is set */
    SRC = (unsigned int)srcBuff;
    A_B_CNT = ((1 << 16u) | (512 & 0xFFFFu)); /* ACNT = 512, BCNT = 1 */
    DST = (unsigned int)dstBuff;
    SRC_DST_BIDX = (512 << 16u) | (512 & 0xFFFFu); /* SRC_BIDX = 512, DST_BIDX = 512 */
    LINK_BCNTRLD = (1 << 16u) | 0xFFFFu; /* LINK = 0xFFFF, BCNTRLD = 1 */
    SRC_DST_CIDX = 0;
    CCNT = 1;

    /* Step 3: Triggering the Transfer and Waiting for Transfer Completion */
    ESR = 0x1;
    while(((IPR) & 0x1) == 0);

    /* Transfer has completed, clear the status register. */
    ICR=0x01;

    /* Transfer is complete. Compare the srcBuff and dstBuff */

     

    I have modified it as follow

    /********************   modified by Jia Tang   ***************/

    /* EDMA register address and definitions */

    //  0x01C00000 is tms320c6747 's base addr
    #define EDMA_CC_BASE (0x01C00000)                                                                          

    //because tms320c6747 doesn't have DCHMAP0,I commented it
    //#define DCHMAP0 *((volatile unsigned int *)(EDMA_CC_BASE + 0x0200))                

    #define DMAQNUM0 *((volatile unsigned int *)(EDMA_CC_BASE + 0x0240))
    #define QUEPRI *((volatile unsigned int *)(EDMA_CC_BASE + 0x0284))
    #define EMCR *((volatile unsigned int *)(EDMA_CC_BASE + 0x0308))
    #define EMCRH *((volatile unsigned int *)(EDMA_CC_BASE + 0x030C))
    #define QEMCR *((volatile unsigned int *)(EDMA_CC_BASE + 0x0314))
    #define CCERRCLR *((volatile unsigned int *)(EDMA_CC_BASE + 0x031C))
    #define QWMTHRA *((volatile unsigned int *)(EDMA_CC_BASE + 0x0620))
    #define ESR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1010))
    #define IPR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1068))
    #define DMAICR *((volatile unsigned int *)(EDMA_CC_BASE + 0x1070))

    #define PARAMENTRY0 (0x01C04000)                            //0x01C04000 
    #define OPT *((volatile unsigned int *)(PARAMENTRY0 + 0x00))
    #define SRC *((volatile unsigned int *)(PARAMENTRY0 + 0x04))
    #define A_B_CNT *((volatile unsigned int *)(PARAMENTRY0 + 0x08))
    #define DST *((volatile unsigned int *)(PARAMENTRY0 + 0x0C))
    #define SRC_DST_BIDX *((volatile unsigned int *)(PARAMENTRY0 + 0x10))
    #define LINK_BCNTRLD *((volatile unsigned int *)(PARAMENTRY0 + 0x14))
    #define SRC_DST_CIDX *((volatile unsigned int *)(PARAMENTRY0 + 0x18))
    #define CCNT *((volatile unsigned int *)(PARAMENTRY0 + 0x1C))


    /* Allocate srcBuff and dstBuff. Do a cache flush and cache invalidate,if required. */
    static signed char srcBuff[512];
    static signed char dstBuff[512];


    memset( srcBuff, 0, sizeof(srcBuff) );

    memset( dstBuff, 1, sizeof(dstBuff) );


    /* Step 1: EDMA initialization */
    QUEPRI=0x10;
    QWMTHRA =(16<<8u)|(16 & 0xFF);
    EMCR = 0xFFFFFFFF;
    CCERRCLR = 0xFFFFFFFF;

    /* Step 2: Programming DMA Channel (and Param set) */

    //because tms320c6747 doesn't have DCHMAP0,I commented it

    //DCHMAP0=0x0;                                                                                                                 
    DMAQNUM0=0x0;
    OPT = 0x00100000; /* only TCINTEN is set */
    SRC = (unsigned int)srcBuff;
    A_B_CNT = ((1 << 16u) | (512 & 0xFFFFu)); /* ACNT = 512, BCNT = 1 */
    DST = (unsigned int)dstBuff;
    SRC_DST_BIDX = (512 << 16u) | (512 & 0xFFFFu); /* SRC_BIDX = 512, DST_BIDX = 512 */
    LINK_BCNTRLD = (1 << 16u) | 0xFFFFu; /* LINK = 0xFFFF, BCNTRLD = 1 */
    SRC_DST_CIDX = 0;
    CCNT = 1;

    /* Step 3: Triggering the Transfer and Waiting for Transfer Completion */
    ESR = 0x1;
    while(((IPR) & 0x1) == 0);

    /* Transfer has completed, clear the status register. */
    DMAICR=0x01;

    /* Transfer is complete. Compare the srcBuff and dstBuff */
    /****************************************   end   ************************************************************/

     

     I have modified some code and  I have commented where I modified. I set breakpoint at the beginning of program,then I click F10(step over) to debug the program,and I didn't see any change in dstBuff by watch window after I have executed the last line of the code ,and I have looked at the EDMA3 registers in a memory window. All of this registers seem have normal value,but the transfer didn't accomplish.The value of srcBuff didn't copied to dstBuff.

  • Jia Tang said:
    /* Step 3: Triggering the Transfer and Waiting for Transfer Completion */
    ESR = 0x1;

    Set a breakpoint at the ESR = 1; line and run to there. Then tell me what the 8 PARAM register values are at 0x01c04000.

    If your linker command file is set to place the srcBuff and dstBuff in Local L2 addresses, then the EDMA3 Transfer Controller cannot reach them. You must set those addresses to the Global L2 address in the 0x11800000 range. The simplest way to do this is to only use the Global L2 address. Other than some of the boot modes starting the DSP at 0x00800000 (this is true for some DSPs), for the C6747 there is no advantage to using the LL2 address rather than the GL2 address for the DSP code and data.

     

    If this answers your question, please click the  Verify Answer  button below. If not, please reply back with more information.

  • RandyP,

     register                                 addr                                     value

    OPT                                          0x01C04000 :                0x81100000

    // 0x0080B940  is the addr of srcBuff
    SRC                                         0x01C04004 :               0x0080B940        

    //  0x0080BB40  is the addr of dstBuff                               
    DST                                          0x01C0400C :             0x0080BB40                                           
    A_B_CNT                                0x01C04008 :              0x00010200
    SRC_DST_BIDX                   0x01C04010 :              0x02000200
    LINK_BCNTRLD                  0x01C04014 :                0x0001FFFF
    SRC_DST_CIDX                 0x01C04018 :                  0x00000000
    CCNT                                     0x01C0401C :                 0x00000001

    Yes,my linker command file is set to place the srcBuff and dstBuff in Local L2 address,but the SRC register value is the base addr of srcBuff. I don't know whether this value indicate the EDMA3 Trandfer Controller can reach them?

  • Jia Tang said:
    Yes,my linker command file is set to place the srcBuff and dstBuff in Local L2 address,but the SRC register value is the base addr of srcBuff. I don't know whether this value indicate the EDMA3 Trandfer Controller can reach them?

    RandyP said:
    If your linker command file is set to place the srcBuff and dstBuff in Local L2 addresses, then the EDMA3 Transfer Controller cannot reach them. You must set those addresses to the Global L2 address in the 0x11800000 range.

    You may either add 0x11000000 to srcBuff and to dstBuff for the SRC and DST fields, or you may change you linker command file to only use the GL2 addresses and not the LL2 addresses.

    Are you using a BIOS project or a non-BIOS project? For a BIOS project, you would make these changes in the tcf Configuration File. For a non-BIOS project, you would edit the linker command cmd file.

  • RandyP,

    Thank you!  I have solved this problem in the way you told me.

    I appreciate your helping me these days.