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.

EDMA3 examples with NOR flash (8-bit)

I'm trying to convert one of the CSL examples to copy from flash with EDMA3 in ab sync mode.  If I understand correctly, the A and B count should allow me to copy 2 megabytes.  For one of the CSL examples, it copies the first 32k, then stops.   I converted the project to operate on big endian, moved the src arrays to point to flash, and the destination arrays to DDR2 memory.  Cacheing is disabled for my initial implementation, to reduce my problem space.   The CSL examples I've tried are edma_self-chain, and edma_interrupt.  QDMA would be fine too, as long as the solution is non-complicated.  

If the flash is in 8-bit mode, does the size of the transfer for the options parameter need to be 8 bits?  Also, then, the ab count would be 0x0031_FFFF as there are 32 64KB transfers, or 32 arrays of 64k bytes.   

Any suggestions on what I might be not setting correctly for my transfer to work?  

Thanks, 

Processor: C64+.  Transfer size =~ 2 megabytes. CCS 5.x,   

EDMA 3 used

  • ixworks,

    Which device are you using and which CSL version are you using? EDMA3 features may vary a lot between the variations, so we need to be talking about the same thing.

    We can find some improvements in several of the older CSL examples for EDMA3, so I will look for any that I re-wrote for your device, if I used it.

    If this read from Flash is part of initialization and is not a real-time constrained transfer, then QDMA would probably be perfect. The settings are (almost) the same for DMA and QDMA transfers. So once we get one working for you, you can change to the other if you prefer.

    ixworks said:
    If the flash is in 8-bit mode, does the size of the transfer for the options parameter need to be 8 bits?

    No. Once you have the EMIF setup to recognize the external device as 8 bits wide, the EMIF will handle translations between 16- or 32-bit accesses on the DSP side of the EMIF to 8-bit accesses on the pins side of the EMIF. You can do 32-bit or even 64-bit accesses if you want on the inside, and the EMIF will do the right number of 8-bit transactions to build what you have requested.

    ixworks said:
    Also, then, the ab count would be 0x0031_FFFF as there are 32 64KB transfers, or 32 arrays of 64k bytes.

    The lower half-word is the ACNT field and the upper half-word is the BCNT. You could use ACNT=1024 and BCNT = 2048 to get a total of 2MB (technically 2MiB if we use the new terminology - I do not care for it but it does make things very clear). Both ACNT and BCNT are limited to 2**16-1 or 65535 for the counts; I usually take that to mean they are limited to 2**15 just to avoid the funny numbers. That is still plenty for a 1GB transfer, so not much of a limitation here.

    ixworks said:
    Any suggestions on what I might be not setting correctly for my transfer to work?

    Leaving cache off is a good plan for now. When you send the device and CSL rev I will look for my notes on those examples and get something back to you.

    Regards,
    RandyP

  • Hi RandyP,

    Thanks for your answer. I am using the C6457, with CSL Version: C6457 03_04_03_01.


    Thanks,
  • Ixworks,

    Here is a project that is configured to work with the C6657 using EDMA3 CSL, DSPMemSpeed.zip. I think it was exported from CCSv5 about 3 years ago. The CSL source files that it uses are included in the project directory, and it looks like only soc.h was modified from the CSL I started from. It 'should' be compatible with your CSL. The main.c file can be configured with #defines for several different processors, and this one is ready for the C6657. It initializes the EDMA3, several channels, and copies from a source location to a destination to determine the best possible speed. I would recommend setting it for L2 to DDR to get it running the first time, then figure out which parts you may want to pull out. main.c is pretty ugly with all the #if/else switches, so it will be a challenge to figure it out. We can talk it out here as needed.

    DSPMemSpeed.zip

    Also attached is a project on the C6455 that is a little more straightforward to read through. It also has a better version of the EdmaIntDispatcher than what comes with the CSL package (I never got anyone to include my updates, so it is not official, but it works better, imho). The changes to get it to work on the C6657 will be minor but important, like Shadow Regions and addresses, all of which should be taken care of in soc.h. This was originally run on CCSv4, but again the source files will work out in any release of CCS.

    C6455_Edma.zip

    Let me know if this just raises more questions or if you get any help from these.

    Regards,
    RandyP

  • RandyP,

    Thanks for your response. When I looked at the examples, they are much like the CSL examples. I am able to perform 32 KB and 64 KB transfers, but it is limited to those. It might be easier to ask what I am doing wrong with my approach.


    In the CSL example for self-chaining, I'm setting the sync mode to AB, the A count is 32k, the B count is 64. Does the BIDX register (32-bits) should then have high and low get set to 0x8000 (32 KB)? I register an interrupt and capture it. I also have seen my transfer time jump by changing the a b counts, but the data never makes it from flash to DDR2.

    Is this the approach that I should take? Am I setting the registers correctly? Why is there a time increase, but data isn't being transferred completely? (32 KB is all that makes it over).

    Thanks,

    Ixworks
  • RandyP,

    I was able to demonstrate 2 megabytes does transfer using intermediate chaining. I had to construct the data size to be less for the A count, as well as use A synchronization (not absync). The array and byte count needed to be populated , with ccnt=1. The src and dst bidx were the a count transfer size.  Transfer time was on par with using one of the methods you suggested in a previous post using 8-byte DSP intrinsic calls (I.e., amemd8).  The bottleneck being the 8-bits of data.  The great thing is that while that is going on, the processor is off doing other things.  I'll have to see if I have a dedicated TC, or if I can use one of the existing and not cause latency for the other transfers in the system. 

    Thanks again for your help,

    IxWorks

  • IxWorks,

    The fact that you have transfers running is a pretty good sign, but it is still easier to work from tested code. In this case, I will remove the CSL examples from the 'tested code' category, unfortunately. But my sample programs are not ideal for what you are doing, either.

    Please post your EDMA3 function, preferably a C file and maybe one header file if needed. I will take a look and see what can be done. When you post your reply, click the "Use rich formatting" link in the bottom-right under the reply box to get more options. One of the links there is "Insert file". It appears to put in a huge glob when you use it, but the post comes out looking like mine did above, with just links.

    Self-chaining is an advanced thing that has its place, but not here. You can do what you want without it and what you want really should be done without it. Mainly, it adds operational complexity and burden and slows the performance, although getting it to work is better than having it not work but being efficient :) .

    BIDX is two 16-bit fields, not a 32-bit field - separate source and destination indexes.

    ixworks said:
    The great thing is that while that is going on, the processor is off doing other things.  I'll have to see if I have a dedicated TC, or if I can use one of the existing and not cause latency for the other transfers in the system.

    {You are very tricky adding things to your posts after the initial reply (comes out in an email). I have to re-read your post to get everything rather than just the email. But it is better to edit it to add in the extra, rather than adding a second post, in my opinion.}

    If you are looking for a dedicated TC and worrying about latency for other transfers, then this is not a strictly initialization-time operation. Is that correct, or am I reading too much into this statement? A 2MB transfer from Flash should not have to happen very many times, but we can discuss latency and interference after getting it to work. Actually, that could be a case for self-chaining, but the individual transfers need to be much bigger than 64 bytes, though.


    Regards,
    RandyP

  • RandyP,

         Thanks for the heads up on the CSL library.   Here's a quick setup- its basically the only delta from the emda self-chaining code.  The addrs are not the same so I could test out flash/ddr2.  The linker command file DOES not allow the compiled code to end up where I'm copying data, so imagine an offset in RAM from the base, so the compiled code isn't trampled on (e.g., linker command memory for DDR2  DDR2:  o =0xE6000000 l=0x90000000.   There are no *.h files that I have changed, so none are attached.  This is strictly starting from the CSL Examples folder, with no caching, no BIOS configuration file. 

    I've attached the complete single file, per your request.

     

    /*  ============================================================================
     *   Copyright (c) Texas Instruments Inc 2002, 2003, 2004, 2005, 2006
     *
     *   Use of this software is controlled by the terms and conditions found in the
     *   license agreement under which this software has been supplied.
     *   ===========================================================================
     */
    
    /** ============================================================================
     *
     *   @file  edma_self_chaining.c
     *
     *   @path  $(CSLPATH)\example\edma\edma_self_chaining\src
     *
     *   @desc  Example of EDMA
     *
     *  ============================================================================
     *   @n Target Platform: 
     *  ============================================================================
     *   @n <b> Example Description </b>
     *   @n This example illustrates a  EDMA Self chaining. The following steps 
     *      shows the EDMA3 setup and illustration of the broken up smaller packet 
     *      transfers.      
     *        1. Initializes the CSL EDMA module
     *        2. Opens and Sets up Edma module to default values 
     *        3. Opens EDMA channel 0 in the region 5
     *        4. Sets up the EDMA PARAM entry 
                 - Enables intermediate transfer chaining to break up a large 
                   transfer into smaller transfers
                 - Sets up the A-synchronized transfer to move a 16K bytes of memory
                 - Sets up to transfer 16 arrays of 1 Kbyte elements, for a total 
                   of 16K byte elements
                 - Sets TCC value as the channel number (channel 0)
                 - Sets TCINTEN to trigger interrupt 0 when the last 1 Kbyte array 
                   is transferred
     *        5. Enable the channel 0 
     *        6. Manually triggers the channel 0
     *        7. Waits for EDMA transfer till it will complete the 16K byte transfer
     *        8. Does the data comparision to ensure the transffered data is proper  
     *           or not and 
     *        9. Displays the messages based on step 8
     *
     * =============================================================================
     *      
     *   <b> Procedure to run the example </b>
     *   @verbatim
     *      1. Configure the CCS setup to work with the emulator being used
     *      2. Please refer CCS manual for setup configuration and loading 
     *         proper GEL file
     *      3. Launch CCS window
     *      4. Open project Edma_self_chain.pjt
     *      5. Build the project and load the .out file of the project.
     *          
     *   @endverbatim
     *
     */
    
    /* =============================================================================
     *  Revision History
     *  ===============
     *  8-Feb-2006 ds    File Created
     * =============================================================================
     */
     
    #include <stdio.h>
    #include <csl_edma3.h>
    #include <soc.h>
    #include <c6x.h>
    
    /* Number of bytes to transfer */
    #define NOF_BYTES_XFR   0x200000
    
    /* Globals */
    //Uint8       srcBuff1[NOF_BYTES_XFR];
    Uint8*       srcBuff1;
    Uint8*       dstBuff1;
    Uint32      passStatus = 1;   
    
    /* Forward declaration */
    void edma_self_chaining (void);
    
    /*
     * =============================================================================
     *   @func   main
     *
     *   @desc
     *     This is the main routine for the file.
     *
     * =============================================================================
     */
    void main(void)
    {   
    	edma_self_chaining ();
        return;   
    }
    
    /*
     * =============================================================================
     *   @func  edma_self_chaining
     *  
     *   @arg
     *      NONE
     *
     *   @desc
     *      This example illustrates a  EDMA Self chaining. The following steps 
     *      shows the EDMA3 setup and illustration of the broken up smaller packet 
     *      transfers.
     *        1. Initializes the CSL EDMA module
     *        2. Opens and Sets up Edma module to default values 
     *        3. Opens EDMA channel 0 in the region 5
     *        4. Sets up the EDMA PARAM entry 
              5. Enable the channel 0 
     *        6. Manually triggers the channel 0
     *        7. Waits for EDMA transfer till it will complete the 16K byte transfer
     *        8. Does the data comparision to ensure the transffered data is proper  
     *           or not and 
     *        9. Displays the messages based on step 8
     *          
     *   @return
     *      NONE
     *
     * =============================================================================
     */
    void edma_self_chaining (void)
    {
        CSL_Edma3Handle             hModule;
        CSL_Edma3HwSetup            hwSetup;
        CSL_Edma3Obj                edmaObj;
        CSL_Edma3ParamHandle        hParamBasic;
        CSL_Edma3ChannelObj         chObj;
        CSL_Edma3CmdIntr            regionIntr;
        CSL_Edma3CmdDrae            regionAccess;
        CSL_Edma3ChannelHandle      hChannel;
        CSL_Edma3ParamSetup         myParamSetup;
        CSL_Edma3Context            context;
        CSL_Edma3ChannelAttr        chAttr;
        CSL_Status                  status;
        CSL_Edma3HwDmaChannelSetup  dmahwSetup;
        volatile Uint32             loopIndex;
        Uint32                      numXfr;
          srcBuff1 = (Uint8*) 0xb0000000;	// hard code addresses.
        dstBuff1 = (Uint8*) 0xe0000000;  // ensure linker command file is clean here. 
        /* Module Initialization */
        status = CSL_edma3Init(&context);
        if (status != CSL_SOK) {
            printf ("Edma module initialization failed\n");   
            return;
        }
        
        /* Module level open */
        hModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&status);
        if ( (hModule == NULL) || (status != CSL_SOK)) {
            printf ("Edma module open failed\n");    
            return;
        }
        
        /* Module setup */
        dmahwSetup.paramNum = 0;
        dmahwSetup.que      = CSL_EDMA3_QUE_0;
        hwSetup.dmaChaSetup = &dmahwSetup;
        hwSetup.qdmaChaSetup = NULL;
        status = CSL_edma3HwSetup(hModule,&hwSetup);
        if (status != CSL_SOK) {
             printf ("Hardware setup failed\n");
             CSL_edma3Close (hModule);
             return;
        } 
          
        /* DRAE enable(Bits 0-15) for the shadow region 5 */
        regionAccess.region = CSL_EDMA3_REGION_5 ;
        regionAccess.drae =   0xFFFF ;   
        regionAccess.draeh =  0x0000 ;
        status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, \
                                   &regionAccess); 
        if (status != CSL_SOK) {
            printf ("Edma region enable command failed\n");
            return;
        }
    
        /* Channel 0 open in context of shadow region 5 */
        chAttr.regionNum = CSL_EDMA3_REGION_5;
        chAttr.chaNum = CSL_EDMA3_CHA_DSPINT;
        hChannel = CSL_edma3ChannelOpen(&chObj, CSL_EDMA3, &chAttr, &status);   
        if ((hChannel == NULL) || (status != CSL_SOK)) {
            printf ("Edma channel open failed\n");
            return;
        }
        
        /* Obtain a handle to parameter set 0 */
        hParamBasic = CSL_edma3GetParamHandle(hChannel,0,&status);
        if (hParamBasic == NULL) {
            printf ("Edma get param handle for param entry 0 failed\n");    
            return;
        }
    
        myParamSetup.option = CSL_EDMA3_OPT_MAKE (CSL_EDMA3_ITCCH_EN, \
                                                   CSL_EDMA3_TCCH_DIS, \
                                                   CSL_EDMA3_ITCINT_DIS, \
                                                   CSL_EDMA3_TCINT_EN,\
                                                   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)srcBuff1;         
        //myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(numXfr, 16);
        myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(0x4000, 0x80);
        myParamSetup.dstAddr = (Uint32)dstBuff1;        
        myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0x4000, 0x4000);
        //myParamSetup.srcDstBidx =  CSL_EDMA3_BIDX_MAKE(0, 0);
    
        myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
        myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(1, 1);
        myParamSetup.cCnt = 1;
        status = CSL_edma3ParamSetup(hParamBasic, &myParamSetup);
        if (status != CSL_SOK) {
            printf("Edma parameter entry setup is failed\n");
            return;
        }
        
        /* Enable channel */
        status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE, \
                                           NULL);
        if (status != CSL_SOK) {
            printf("Edma channel enable command is failed\n");
            return;
        }
        
    #if 1 /* change to 0 if performing timing */
        /* Initialize data */
        for (loopIndex = 0; loopIndex < NOF_BYTES_XFR; loopIndex++) {
     //       srcBuff1[loopIndex] = loopIndex;
            dstBuff1[loopIndex] = 0;
            
        }
    #endif
        /* Manually trigger the channel */
        status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
        if (status != CSL_SOK) {
            printf("Edma channel set command is failed\n");
            return;
        }
        
        regionIntr.region = CSL_EDMA3_REGION_5;
        regionIntr.intr = 0;
        regionIntr.intrh = 0;
        
        do {
            /* Poll on interrupt bit 0 */
            CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);
        } while (!(regionIntr.intr & 0x1));
    
        /* Clear interrupt bit 0 */
        status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR, \
                                   &regionIntr);   
        if (status != CSL_SOK) {
            printf("Edma clear interrupt bit 0 command is failed\n");
            return;
        }
        // commented out for timing
        /* Check transfer */
     //   if(Verify_Transfer(NOF_BYTES_XFR, 1, 1, 0, 0, 0, 0, srcBuff1, dstBuff1, \
     //                      TRUE) == FALSE) {
     //      passStatus = 0;
     //   }
               
      //  if (passStatus == 1)
    //        printf ("<<EXAMPLE PASSED>>: Edma Self Chaining Transfer Passed\n");
    //    else {
    //        printf ("<<EXAMPLE FAILED>>: Edma Self Chaining Transfer Failed\n");
    //        return;
      //  }
     //
        
        /* Close channel */
        status = CSL_edma3ChannelClose(hChannel);
        if (status != CSL_SOK) {
            printf("Edma channel close failed\n");
            return;
        }
        
        /* Close edma module */
        status = CSL_edma3Close(hModule);
        if (status != CSL_SOK) {
            printf("Edma module close failed\n");
            return;
        }
        
        printf ("=============================================================\n");
        
        return;
    }
    
    

    myParamSetup.option = CSL_EDMA3_OPT_MAKE (CSL_EDMA3_ITCCH_EN, \

    CSL_EDMA3_TCCH_DIS, \

    CSL_EDMA3_ITCINT_DIS, \

    CSL_EDMA3_TCINT_EN,\

    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)srcBuff1;

     myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(0x4000, 0x80);

    myParamSetup.dstAddr = (Uint32)dstBuff1;

    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0x4000, 0x4000);

     myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);

    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(1, 1);

    myParamSetup.cCnt = 1;

    status = CSL_edma3ParamSetup(hParamBasic, &myParamSetup);

    In your email inbox, I was using my starting post as a work-in-progress draft.  We all have scars from a past life where using Editors meant you save every 5 minutes, or perish (work lost).  Therefore, you may have gotten extraneous information, as you will because I've edited it twice three times in an attempt to add clarity and coherence.

    Thanks for any insight and help.  The code above is to transfer 16KB chunks until 2 MB is reached.  In theory, I should be able to use 32k, with the SRC/DST BIDx registers, but, if my memory serves me correctly, something wasn't working with that setup and I didn't spend much time on why. 

    -ixworks

  • IxWorks,

    Your EDMA3 channel setup looks good above. I would recommend you _DIS the ITCCH parameter for testing, just to take that out of the set of possible problems. I would use multiple manual triggers (writes to ESR) to trigger each transfer. This will also allow you to watch how the parameters change during the sequence of triggers.

    In the example code, one of the wrong things that is in several of our examples is the initialization of the channel mapping. The code that does the HwSetup seems to luck out and only try to use channel 0 which may accidentally get setup. The code you are using came that came from that includes the following:

       CSL_Edma3HwDmaChannelSetup  dmahwSetup;

       /* Module setup */

       dmahwSetup.paramNum = 0;

       dmahwSetup.que      = CSL_EDMA3_QUE_0;

       hwSetup.dmaChaSetup = &dmahwSetup;

       hwSetup.qdmaChaSetup = NULL;

       status = CSL_edma3HwSetup(hModule,&hwSetup);

    However, the CSL_edma3HwSetup function assumes that the second parameter is a struct with two pointers to arrays of structs, but this code sets .dmaChaSetup to the address of a single struct. The CSL_edma3HwSetup function will still step through the whole array anyway, even though it will be putting trash into a bunch of EDMA3 configuration registers. Since the values are only intended for channel 0 and since the values intended are the same as what gets put there by a reset, it is hard to tell whether the right values are even written for channel 0.

    The right way to do this is with the following code:

    CSL_Edma3HwDmaChannelSetup dmahwSetup[CSL_EDMA3_TPCC_NUM_DMACH] =

    CSL_EDMA3_DMACHANNELSETUP_DEFAULT;

    CSL_Edma3HwQdmaChannelSetup qdmahwSetup[CSL_EDMA3_TPCC_NUM_QDMACH] =

    CSL_EDMA3_QDMACHANNELSETUP_DEFAULT;

       /* Module setup */

       dmahwSetup[0].paramNum = 0; // fyi for clarity, not needed, default

       dmahwSetup[0].que      = CSL_EDMA3_QUE_0; // fyi for clarity, not needed, default

       dmahwSetup[8].paramNum = 8; // fyi for clarity, not needed, default

       dmahwSetup[8].que      = CSL_EDMA3_QUE_0; // fyi for clarity, not needed, default

       hwSetup.dmaChaSetup = dmahwSetup;

       hwSetup.qdmaChaSetup = qdmahwSetup;

       status = CSL_edma3HwSetup(hModule,&hwSetup);

    This code passes full arrays that are initialized to the default values. As the comments for channels 0 & 8 say, these are just thrown in to show how to use them but are redundantly setting the same values to these struct contents.

    The channel enable code is not needed for this code. It sets the EER (Event Enable Register) bit for this channel but you are using ESR to trigger it and CER for chaining, neither of which have to be enabled. This is the code I mean, and it can be #if'd out:

       /* Enable channel */

       status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE, \

                                          NULL);

       if (status != CSL_SOK) {

           printf("Edma channel enable command is failed\n");

           return;

       }

    For testing, I will suggest the changes above and then duplicate the Channel Set code a few times, then step through them and watch what happens in the EDMA3 PARAM for channel 0. You can find that in the Registers Window or in a Memory Browser at whatever address it says, usually at the address of the EDMA3CC Channel Controller plus 0x4000.

    I would be interested to see the hex values in PARAM0 just before stepping over the first manual trigger, then again just before the next 2-3 of them. And then also the contents of memory at the source and destination to see how what happens in memory compares to what the PARAM entries say is happening. It would help for debug to change ACNT to 0x20, and both of the BIDX fields also to 0x20.

    After working through this chaining example, if you want, we should try to figure out why you are having trouble getting it to work in a single AB-sync trigger. But, if you have an issue with interfering with other memory bus operations during this time and you really need to do this with chaining, we can drop that part. That will be up to you.

    Regards,
    RandyP