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.

Opening more than 2 channels in EDMA3

Other Parts Discussed in Thread: TMS320C6670

Hi, in the given EDMA3 sample code under \edma3_lld_02_11_05_02\examples for TMS320C6670, I could open only 2 channels to perform a DMA transfer(2 channels max needed for the given same code). In my application, its required that I need more than 2 channels to perform few set of transfers. After opening two channels, if I try opening another channel using the API result = EDMA3_DRV_requestChannel (hEdma, &chId, &tcc,(EDMA3_RM_EventQueue)0,&callback1, NULL);

it returns result as a negative number as the third channel couldn't be opened. I believe I need to change the sample configuration file sample_c6670_cfg.c
What changes should be made so that I can open more than 2 channels. Or is there any other way. PLEASE HELP.

Regards

Sud

  • Hi Sud,

    I am going to move your post to the BIOS forum. Hopefully someone will answer it soon.

    Thanks and regards,

    Tai

  • Hi Tai, thanks for the reply. I don't think its related to BIOS. Its something related to EDMA3 initialization in the given sample example. The EDMA3 Init in the sample example is written such that each shadow region in each EDMA3 instance can allow opening of only 2 channels. How ever this can be changed by modifying the sample configuration file sample_c6670_cfg.c
     Anyway, hopefully I get a solution from the BIOS forum.

    Regards

    Sud 

  • Sud,

    After spending some time looking at the files in the LLD and the cfg file you reference, I do not see what would be causing your limitation.

    Can you be specific about the following, please:

    • which example are you running?
    • what are your arguments for the 3 calls to EDMA3_DRV_requestChannel (hEdma, &chId, &tcc,(EDMA3_RM_EventQueue)0,&callback1, NULL)?
    • exactly where do you find that "EDMA3 Init in the sample example is written such that each shadow region in each EDMA3 instance can allow opening of only 2 channels"?
    • why do you believe this is related to the contents of sample_c6670_cfg.c?

    To try to debug this in your application, it will be easiest if you can source-step into the file that defines the EDMA3_DRV_requestChannel function, edma3_drv_basic.c. If your lld library is built with debug enabled, then you may be able to do that without doing anything else. Otherwise, you may have to either include that source file in your project or include all the library source in your project or rebuild the library with source debugging enabled. I would try those 4 choices in that order, since I do not know how to rebuild the library with debugging enabled.

    Regards,
    RandyP

  • RandyP,

    Thanks for the reply and taking some of your time looking into the files. Well, let me be more specific.

    1. I'am running the example under \ti\edma3_lld_02_11_05_02\examples\edma3_driver\evm6670

    2. May be this picture would help.

    In the present example, I could able to open only 2 dma channels. If I try to open more than 2, it throws result a neg. value, which means opening of the channel failed.

    3&4. I ran it on Core0, instance0(and shadow region 0) , the channel numbers which I got was ch1=2, ch2=3, as in the picture. And 3rd channel, well it dint let me open.
    If I run it on Core1, instance0(and shadow region 1), the channel numbers which I get is ch1=6, ch2=7. And as the same, it wont allow me to open a 3rd channel.

    So, what my guess is, initialization is done in such a way that, only 2 channels is allowed to be opened per instance per core or what so ever. Why I guess is, 2 channels is only needed at max in the given sample example(2 channels needed in dma chaining).
    And as I looked into the edma3init() function in sample_init.c, the driver initialization is done by the piece of code 

    /* Hook for running examples with default RM config */
    /* configuration structure for the Driver */
    initCfg.drvInstInitConfig = &sampleInstInitConfig[edma3Id][dsp_num];

    and sampleInstInitConfig is defined as:

    for instance0, shadow0

    what does 

    /* ownDmaChannels */
    /* 31            0         63            32 */
    {0x0000000Fu, 0x00000000u},   

    really mean? I know that 0xF means 16, so 16 channels should be owned by this shadow region instance.

    And you scroll down for shadow region 1 its

    /* ownDmaChannels */
    /* 31            0         63            32 */
    {0x000000F0u, 0x00000000u},

    And for instance1, shadow region 0

    /* ownDmaChannels */
    /* 31            0         63            32 */
    {0x0000FFFFu, 0x00000000u},

    0x0000FFFF = 65535 and theres no way instance1 has so many channels. So it has to do something with bit pattern.
    Well, this is just a wild guess that edma initialization is done such that only 2 channels can be opened which serves the need for the present sample example. I MAY BE WRONG TOO!
    You can just run the sample example and try opening 3 or more channels. 
    Well, is there any way that I can request/open more that 2 channels. In my application, which I ll be developing, I would need atleast 9 dma channels opened, ready and to be used. 



    By the way, I did include all the library source files in a separate project which I made. So that I can enter into each libraries and look in how its written and works.



    Regards -

    sud 

  • Sud,

    The pictures help a lot. And thank you for your patience as we work through this. Since the EDMA3 Resource Manager User Guide (EDMA3_RM_User_Guide.pdf) does a much better job of detailing some of the struct fields, I will not try to go into that much detail, but will try to share my understanding of what is happening and your choices of how to get around it.

    You are ABSOLUTELY CORRECT that the problem you are seeing is due to the configurations provided in sample_c6670_cfg.c. Like many samples or examples, some specific things are being demonstrated and the rest of the resources are handled arbitrarily. That arbitrary handling is what is stopping you from getting the third channel allocated. So the configuration is not necessarily wrong, just arbitrary; and it does not match with what you want to do.

    My first thought of a solution will not work. That would be to use EDMA3 Instance 1 or 2. Both of these have 64 channels to work with, while Instance 0 only has 16 channels to work with. If you changed your code to use either of those, it should work, in my opinion, but it will not without making other changes. This is because the allocations are done in a hardware oriented way, preferring to reserve DMA channels for hardware events instead of for software events like you want to do.

    The reason the DMA channels are reserved for hardware events is that this is the best use of a DMA channel. The next best use of a DMA channel is for chaining after a hardware event's DMA channel has completed.

    Instead of using a DMA channel for a software-triggered transfer, it is common to use a QDMA channel. The setup and programming is handled a little differently, but it does the same transfer and can generate an interrupt when it completes. The great advantage of QDMA is that you can start a new, similar transfer by only writing 1 or a few PARAM words whenever the other PARAM words do not need to change.

    But... there are only 8 QDMA channels per EDMA3 Instance. So this is still a limited resource, and would not help in your case because there is still a limitation to the number of TCC values that are easily available to use for either DMA or QDMA channels.

    One solution that will get a third channel for your specific test would be to set ch3=0 and tcc3=0 before the third call to EDMA3_DRV_requestChannel. By the way, I recommend you change the name of hEdma to hEdma0 so it will be clear that you are working with EDMA3 Instance 0. By specifying the channel number and the TCC value, you can use one of the reserved channels as if you were going to use this channel for a hardware event. You could also specify ch4=1 and tcc4=1 to get a fourth channel. This is because the sample_c6670_cfg.c file has sampleInstInitConfig[0][0] configured to let region 0 own 4 DMA channels and 2 QDMA channels and 4 TCC values, but it reserves 2 DMA channels and 2 TCC values for hardware event that require a specific channel. If you are not using those channels, then you can request them explicitly and you can then use those remaining 2 channels for software-triggered transfers. You might be able to do the same thing with the 2 QDMA channels, but since there are still only 2 remaining TCC values, you would have to use those by explicitly selecting them for QDMA, also (if that works, I have not studied that part of it very much).

    The other solution is to change the allocation of channels in sample_c6670_cfg.c. If you study the explanations in the EDMA3 Resource Manager User Guide (EDMA3_RM_User_Guide.pdf) and compare those explanations to the sample configuration in sample_c6670_cfg.c, you can figure out the way you want to allocate all of your channels.

    Here are some answers to your questions, followed by some general comments that may help. It all seems complicated because it is robust and powerful and flexible, but it is a lot of data to completely understand. You have already learned a lot of it, and you will be one of the few experts when you are done with this, so please keep coming back to the forum to answer people's questions when you see them walking the same path as you have.

    Sudarshan R said:

    what does

    /* ownDmaChannels */
    /* 31            0         63            32 */
    {0x0000000Fu, 0x00000000u},  

    really mean?

    All of the values in the sampleInstInitConfig array are bit fields, with each bit representing a single channel or TCC value or PARAM set or such. In this case, EDMA3 Instance 0 Region 0 is set to own 4 DMA channels, 0-3. This should be mutually exclusive from this field for the other Regions of Instance 0; you do not want any channels to be owned by more than one Region.

    The way this works is that you decide which DMA channel numbers will be owned by this Region and you will usually have the corresponding TCC values owned by this Region, also. Then you will choose which of these DMA channels should be reserved for hardware events by setting the corresponding bits in the resvdDmaChannels field. The DMA channels that are owned by a Region and are not reserved for that Region, these are the DMA channels that can be returned from EDMA3_DRV_requestChannel when you set ch3 to EDMA3_DRV_DMA_CHANNEL_ANY, since those channels are *not* reserved for hardware events. And this is why you can still use them if you explicitly specify the channel number in the call to EDMA3_DRV_requestChannel .

    Sudarshan R said:
    Well, this is just a wild guess that edma initialization is done such that only 2 channels can be opened which serves the need for the present sample example.

    You are correct. Because 4 DMA channels are owned and 2 are not reserved, only two DMA channels are available for the call to EDMA3_DRV_requestChannel using ch3=EDMA3_DRV_DMA_CHANNEL_ANY.

    Sudarshan R said:
    Well, is there any way that I can request/open more that 2 channels. In my application, which I ll be developing, I would need at least 9 dma channels opened, ready and to be used.

    Now we are getting to the part where you have to modify sample_c6670_cfg.c to match the requirements of your application. For example, do you require 9 DMA channels for CorePac0 to use, plus 9 for CorePac1, and so on, or only 9 total? Do these need to be on EDMA3 Instance 0, or can you use Instance 1 or 2? And which hardware events will you need to use elsewhere in your application, if any, and by which CorePacs?

    These are all the questions you need to figure out, and then you can start the process of doing the reallocation to match what you need. Maybe a good series of questions are:

    1. Which hardware events need to be used? These need to be owned and reserved by one Region corresponding to the CorePac that you plan to configure and receive interrupts from those channels.

    2. Limit EDMA3 Instance 0 to data being moved within and between MSMCSRAM and DDR3. Instance 0 is especially powerful for this, and is not any better at other transfers than Instances 1 and 2. Anything else should be done on Instances 1 and 2, so ask yourself which CorePacs need to do MSMCSRAM and DDR3 copies. If you need to move from DDR3 to CorePac1's L2 memory, use Instance 1 or 2.

    3. Allocate the remaining DMA channels among the four CorePacs and let the corresponding Regions own them and their TCCs.

    4. PARAM also needs to be allocated in the various fields.

    I hope this helps some. Please consider these comments, study the corresponding information in the EDMA3 Resource Manager User Guide (EDMA3_RM_User_Guide.pdf), and come back here with any additional questions and especially your new comments of advice based on your new experience.

    Regards,
    RandyP

  • RandyP,
    BINGO! I set the channel no. and tcc as [ch=0,tcc=0] and [ch=1,tcc=1]. And yes, it was a successful opening of the channels. So, its configured such that it allows region 0 to use 4 DMA channels, in which 2 are reserved. Well, I did few modifications to the file sample_c6670_cfg.c so as to allows more DMA channels. Allow me to share my experience.

    As all of the values in the sampleInstInitConfig array are bit fields, with each bit representing a single channel. I modified it for instance0, region0 as

     /* ownDmaChannels */

    /* 31            0         63            32 */
    {0x000000FFu, 0x00000000u},

    I then ran. It gave me the same problem.
    I then did the same change in  /* ownTccs */ and /* ownPaRAMSets */ so as to allow more TCC values and PaRAM sets. It still din work!

    Then I figured out that few channels are getting overlapped in region1 if I do the above changes. Since, in region1, owned DMA channels are [4,5,6,7] which again I'm assigning to region0 by making the above changes. Hence, theres a clash. So for region1, I made 0 channels allocated by making

    /* ownDmaChannels */
    /* 31            0         63            32 */
    {0x00000000u, 0x00000000u}

    and did the similar changes in region1 for   /* ownTccs */ and /* ownPaRAMSets */ so that theres no clash b/w region0 and region1 for TCCs and PaRAM sets. And I could finally get to open more channels in region0 (8 DMA channels for the above modifications done).  
    And well, about the requirements, I could want a total of 9 DMA channels for CorePac0 and CorePac1. (may be a combinations of 4 DMA channels for Core0, 5 DMA channels for Core1).
    And about the requirements of hardware events, I guess I need to ping my immediate supervisor  about this. Will do so in the next coming working day. Untill then, will just relax the weekend.

    Thanks a lot for all the help. I guess I can move on my own with the understanding of the above comments. If any query occurs, ll ping pack to this same post.
    I hope this post be made useful by others. Since, it was hell of a time cracking what might be the problem for not letting opening more than 2 channels. Thanks again for your help.

    Regards,

    Sud 

  • Hello Sud,

    Thanks so much for this post. I cracked the problem on my own but up to now I only needed four channels.

    Since you seem to have a great understanding of the driver, may I asked you 2 questions that might not take you too much time.

    1)Can you reffer me to a location to understand how the paramset and TCC are configured in memory?

    2) is there a reason why the PaRamSets are not continuous? And some are left unused?

                    /* ownPaRAMSets */
                    /* 31     0     63    32     95    64     127   96 */
                    {0xFFFF000Fu, 0x00000FFFu, 0x00000000u, 0x00000000u,
                    /* 159  128     191  160     223  192     255  224 */
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                    /* 287  256     319  288     351  320     383  352 */
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                    /* 415  384     447  416     479  448     511  480 */
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u},

    I assumed that some are used for DMA and some for QDMA but I am not sure where to look for that.

    Thanks a lot in advance

    Aymeric

  • Aymeric,

    aymeric dupont said:
    1)Can you reffer me to a location to understand how the paramset and TCC are configured in memory?

    The EDMA3_RM and EDMA3_Driver User Guides are available in the LLD installation folder. These are the best documents that I know of.

    aymeric dupont said:
    2) is there a reason why the PaRamSets are not continuous? And some are left unused?

    Each core will have a separate set of resources allocated to it, so one core may have a few channels and another may have many channels. It is up to you how you will allocate the resources between the different cores.

    Regards,
    RandyP