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.

How to use A8 OMX buffer with EDMA?

Other Parts Discussed in Thread: SYSBIOS

Hi,

I am working with TI8168 and EZSDK 5.03, I am trying to use EDMA for data transfers on capture-encode OMX A8 application, the problem is as follows:
I have a buffer declared on an A8 OMX file in the capture-encode example main.c, which gets a virtual address, the EDMA need a physical address in order to transfer data.

1. How can i translate the virtual address to address that can be used by the EDMA?

2. I am trying another approach which is to allocate the buffer in a physical address that i have read at the following post http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/164186.aspx where Tarakesh sais as follows:

You could do this:

Allocate buffers from shared region 2 in A8. Following is the code snippet

#include <ti/syslink/utils/IHeap.h>
#include <ti/ipc/SharedRegion.h>

        IHeap_Handle    heap;

        heap = SharedRegion_getHeap(2);

        Buffer1 = Memory_alloc (heap,MAX_BUF_SIZE, 128, NULL);

I am trying to do this myself but i get the following error message: 

Assertion at Line no: 1081 in /home/gabi/z3/z3-netra/z3-netra-RPS-20120221/ezsdk
/component-sources/syslink_2_00_05_85/packages/ti/syslink/ipc/hlos/usr/SharedReg
ion.c: (id < SharedRegion_module->cfg.numEntries) : failed

Can anyone please help with that?

Thanks,
Gabi 


  • Hi Gabi,

    Did you solved the Shared Region problem? I am also getting the same error.

    I have written simple C file to check the shared region but same result. Below is my source code.

    =========================================================

    #include <stdio.h>

    #include <ti/syslink/Std.h>
    #include <ti/syslink/utils/IHeap.h>
    #include <ti/ipc/SharedRegion.h>
    #include <ti/syslink/utils/Memory.h>

    int main()
    {
        uint8_t *pBuffer = NULL;
        uint32_t IL_CLIENT_SR = 2;
        IHeap_Handle heap = NULL;

        heap = (IHeap_Handle)SharedRegion_getHeap(IL_CLIENT_SR);
        if(NULL == heap)
            printf("Failed to allocate memory from shared region.");
        else
        {
            pBuffer = Memory_alloc(heap, 1382400, 128, NULL);
            if (pBuffer == NULL)
                printf("Memory Allocation successfull from Heap: %p.", heap);
            else
                printf("Allocated buffer from shared region: %0x ", (uint32_t)pBuffer);
        }
        return 0;
    }
    ============================================================

    Regards,

    Krunal

  • Forgot to mention the error:

    Assertion at Line no: 1081 in /home//syslink/packages/ti/syslink/ipc/hlos/usr/SharedRegion.c: (id < SharedRegion_module->cfg.numEntries) : failed

  • Hi Krunal,

    First, i am so happy you replied to this thread, it seems that no one replies to threads in this forum lately.
    Second, no, i didn't solve that problem, furthermore i have more problem as described here:

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/p/203642/723029.aspx#723029

    You might find also these threads interesting as well:

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/p/155685/564349.aspx#564349

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/164186.aspx

    Unfrtunatly no response from TI employees yet. I hope that if more people have similar problem maybe we will get some response.

    Gabi


  • I am working with TI8168 with EZSDK ver 5.03, i am also interesting in using EDMA3 for coping of OMX buffers to another A8 allocated buffers. The problem is that the A8 and OMX buffers has Linux virtual addresses and the EDMA3 need physical addresses, i can't find a way to translate the virtual addresses from the the A8 and the OMX application to physical addresses that can be used by the EDMA3. Did anyone find a way?

    Alla

  • Hi Gabi,

    I am able to use allocate memory from Android. I am looking for a specific use-case.

    I want to allocated Shared Region memory from a separate process which is not part of Android Multimedia process.

    Seems like I need to specify the Shared Region configuration from either the source code or from the build steps (Makefile, .cfg. file).

    I have got some interesting information from IPC user-guide  and working to implement that. I will let you know if anything is fruitful with that.

    Regards,

    Krunal

  • FWIW, I'm going to move this to the "Linux Embedded Software" Forum.  The Hardware forum where this was originally posted isn't monitored by the SW folks, and you're likely to get a better response if SW folks see it.

    Chris

  • Gabi,

    That assertion is occurring because you specified a shared region index that is too large.  You would need to have at least 3 shared regions configured to allocate a buffer from shared region 2.  Here is the Ipc User's guide, which has information on configuring shared regions:

    http://www.ti.com/lit/ug/sprugo6d/sprugo6d.pdf

    Are you loading something on the DSP?  If so, you can look at the .cfg file to find the shared region configuration.  Or, are you only using the A8 for your app?  If that is the case, you may be able to use CMEM (http://processors.wiki.ti.com/index.php/CMEM_Overview) to allocate a contiguous buffer and get its physical address.

    Best regards,

        Janet

  • Hi Janet,

    Thanks for your answer.
    As far as i understand, the TI8168 has 3 shared regions as can be seen here:
    http://processors.wiki.ti.com/index.php/EZSDK_Memory_Map 

    I was trying to allocate memory at shared region 2 (the last shared region with size of 188MB starting at 0xB3D00000) because this is were the OMX allocates its buffers. 
    After reading the IPC User's guide I still don't understand why the lines below are not doing this job for me even tough the heap return a non NULL value that seems correct, 

    heap = (IHeap_Handle)SharedRegion_getHeap(IL_CLIENT_SR);
    pBuffer = Memory_alloc(heap, 1382400, 128, NULL); is not doing this for me  

    i am using both A8 and DSP but the DSP is an OMX component thus not using cmem, it seems like cmem can be used for translating virtual to physical addresses for shared region 2, i will check this out.

    Thanks,
    Gabi 

  • Hi Gabi,

    I hadn't realized that SharedRegion_getHeap() was returning a non-NULL handle.  I am not familiar with OMX, so I don't know where this shared region entry gets created.  According to the EZSDK memory map, this is a shared region between the Arm and the video-m3 and vpss-m3.  Are you loading either of these?  Maybe the OMX app is calling SharedRegion_setEntry() to set up this region.  Could you try calling:

        SharedRegion_Entry     entry;
        SharedRegion_getEntry(2, &entry);

    to see if this entry exists, and what its properties are?

    Best regards,

        Janet

  • Hello Everyone,

    I have solved this problem and now I am able to allocate memory for multiple processes at the same time.

    I would like to share few information which I could know during this based on my reading/discussion and experiments.

    • OMX_Init() function can be called from a single process. If you have multiple processes in your application design which uses OMX, only one process will be able to use OMX_Init() API. This is due to the fact that OMX_Init() create's message queues with specific names and/or other syslink resources for sending and receiving messages. If multiple processes tries to call the same API again they will get some kind of Syslink notify errors and omx will failed to initialize. Attached is the log for reference in case of such failure. 1588.3527.scenario-1_omx_init_errors.txt
    • How to Allocate Shared memory from multiple process: Assuming there are multiple processes in the application design which deals with OMX components and each of the / multiple process wants to allocate memory from Shared Region.
      • Ideal API Sequence for Allocating memory from Shared Region is:
        1. Init omx instance using OMX_Init()
        2. Get heap using SharedRegion_getHeap()
        3. Allocate memory from heap using Memory_alloc()
      • Now as per above sequence OMX_Init() should be called from all the processes that wants to allocate shared memory. But this is not possible because of the limitation of OMX_Init() API described above (bullet-1).
      • In this case one (mostly parent/control) process can use above sequence to allocate memory where as other processes can use below sequence of APIs:
        1. Initialize syslink interface using SysLink_setup()
        2. Get heap using SharedRegion_getHeap()
        3. Allocate memory from heap using Memory_alloc()
    • Note: If you don't call OMX_init() or SysLink_setup() APIs and directly use SharedRegion_getHeap() and Memory_alloc() APIs respectively to allocate Shared memory you will see error log as this 3644.4338.scenario-2_memory_allocation_failed.txt.

    I hope this will help other people for the SharedMemory Allocation.

    Regards,

    Krunal

  • Hi Krunal,

    I have done what you have suggested:

    SysLink_setup();
    printf("after SysLink_setup\n");
    heap = SharedRegion_getHeap(2);
    printf("heap = %x\n",heap);
    A8Buffer0 = Memory_alloc(heap,2*1920*1080, 128, NULL);
    printf("A8Buffer0 = %x\n",A8Buffer0); 

    after doing this the target stuck at Memory_alloc without printing any error message.

    Thanks,
    Gabi 

  • Hi Janet,

    Thank you very much for your answer.
    1. I am loading both video-m3 and vpss-m3.
    2. I have done what you have suggested, i get that entry = 0x44b2f000, does this help?

    Thanks,
    Gabi 

  • Hi Gabi,

    Are you still facing issue with Shared memory allocation?

    I have received email regarding your post from e2e "Hi Krunal, This is great, thanks a lot, this way memory allocation can be done successfully. - Gabi"

    But when I open this thread I am not able to see this post and still see you are facing some issue.

    Regards,

    Krunal

  • Hi Krunal,

    Yes, i am still facing problems with memory allocation.
    Sorry about the confusion, i had a mistake in the tests i have performed, i have tested an older version without any memory allocations at all, when it was working i have wrote what you have seen in the email, after that i double checked myself and found out that allocation is still not working and that i have another problem now so i changed my message at the thread. 

    Let me please ask you a question, are you succeeding in allocating buffers on the A8 within an OMX ilclient program such as capture_encode or decode_display?

    Thanks,
    Gabi 

     

  • Hi Gabi,

    I have done this in Android. However it must work on the linux as well. Did you followed the exact sequence as mentioned in my detailed post?

    Did you checked the decode_mosicdisplay example of OMX (ezsdk/component_sources/examples/decode_mosicdisplay) in ezsdk 5.04. Please note older releases does showcase SharedMemory allocation in OMX examples.

    If it does not work for you, I will try to write an sample application on linux and share with you tomorrow.

    Also, let me know below:

    1. Which ezsdk version you are using
    2. Is it on EVM or customized hardware? If customized, have you done any changes related to memory map?

    Regards,

    Krunal

  • Hi Gabi,

    I just noticed, previously I have already shared sample code on this thread (which was not working). I modified the same logic (marked with green color) and it started working for me.

    Use below code and check if it works for you.

    =========================================================

    #include <stdio.h>
    #include <ti/syslink/Std.h>
    #include <ti/syslink/utils/IHeap.h>
    #include <ti/ipc/SharedRegion.h>
    #include <ti/syslink/utils/Memory.h>

    /* Uncomment this define if OMX_Init() is already done */

    #define OMX_ALREADY_DONE_IN_OTHER_PROCESS 1


    int main()
    {
        uint8_t *pBuffer = NULL;
        uint32_t IL_CLIENT_SR = 2;
        IHeap_Handle heap = NULL;

    #ifndef OMX_ALREADY_DONE_IN_OTHER_PROCESS

        OMX_Init();

    #else

       SysLink_setup();

    #endif
        heap = (IHeap_Handle)SharedRegion_getHeap(IL_CLIENT_SR);
        if(NULL == heap)
            printf("Failed to allocate memory from shared region.");
        else
        {
            pBuffer = Memory_alloc(heap, 1382400, 128, NULL);
            if (pBuffer == NULL)
                printf("Memory Allocation successfull from Heap: %p.", heap);
            else
                printf("Allocated buffer from shared region: %0x ", (uint32_t)pBuffer);
        }
        return 0;
    }
    ============================================================

  • Hi Kurnal,

    Thank you very much for your help.

    1. I am working with EZSDK ver 5.03.
    2. I am working with Z3 board, i haven't done any changes in memory map.

    i didn't update to EZSDK ver 5.04 yet because Z3 are modifying the EZSDK before it can be used on there board and they havedn't released EZSDK ver 5.04 for their board yet. I am working with the capture encode_example and not the decode_mosicdisplay but i don't think it is making any difference.

    Best regards,
    Gabi 

  • I have updated my EZSDK ver to 5.04, in that version there is an OMX example called decode_mosaicdisplay.
    Memory allocation and translation of virtual address to physical is done there as follows:

    heap = SharedRegion_getHeap(IL_CLIENT_SR);

    pBuffer = Memory_alloc (heap, pAppData->decILComp->outPortParams->nBufferSize, 128, NULL);

    pTempBuffer = (OMX_PTR) DomxCore_mapUsrVirtualAddr2phy ((uint32_t)pBuffer);

     

  • Hello Gabi,

    I succeeded in allocating the buffer in SR 2 thanks to your help. I was wondering how you went about using the EDMA in the A8 and DSP. I'm having trouble figuring how best to communicate with the kernel driver (edma_test). On the DSP side, I have tried compiling the demo with my VLPB code as well as including the libraries, 4 of them total, but I get a couple missing symbols. Is there anything you say about these topics?

    -Roberto

  • Hi Roberto,

    The DSP can not use the edma_test similar to the A8, the edma_test uses linux kernel low level driver, in the DSP there is no linux, therefor you should use EDMA_LLD library which is suitable for the DSP/BIOS operating system on the DSP. You should write your something like the edma_test using EDMA_LLD functions. A good start will be the edma example found in

    <ezsdk>/component-sources/edma3lld_xx_xx_xx_02/examples/CSL2_DAT_DEMO/src/dat_edma3LLD/

    Good luck,
    Gabi 

  • Gabi,

    Yes I realized that for the A8 I would have to use the kernel module and for the DSP I would need CSL2_DAT_DEMO. I have resolved using the driver for A8 by using ioctl to communicate with the drive. A very similar use case can be found at http://processors.wiki.ti.com/index.php/TI81XX_PSP_PCI_Express_Endpoint_Driver_User_Guide, which I merged with the one located in the psp examples.

    For the DSP I copied the CSL2_DAT_DEMO into VLPB source and linked the 4 EDMA libraries to the final DSP firmware, but I got unrecognized symbols. If you got this to succeed any help would be appreciated as I may still have use for EDMA in the DSP.

    For now I have developed a way to pass DSP allocated memory to the Arm via a pointer through the VLPB output buffer. This will help to reduce the need to copy by passing structures back to the Arm without a memcpy or dma transfer. There are some downsides to it, but less copying means less wasted memory :)

    Regards,
    Roberto 

  • Hi Roberto,

    Sorry for the long time it took me to answer i was at a long vacation, what EZSDK version are you using? i had some problems compiling the EDMA_LLD in EZSDK 5.04 but they were solved in EZSDK 5.05. 

    Gabi

  • Gabi,

    I am using Ezsdk 5.05 from Z3 tech. Turns out my problem was that I wasn't using the configuration options that were in the example. As soon I added those in it started to work. Anyway, thanks for replying.

    Even using EDMA, we still don't get the kind of performance we need. But perhaps we still need to refine our code and use EDMA in more places.

    Thank you,

    Roberto

  • Hi Robero,

    Are you familiar with writing optimal code for DSP using intrinsic functions?
    Are you familiar with the scheme of slice processing with double input and output buffers copied to/from DSP L2 using EDMA?
    The idea of double buffer is that when the edma copies one input buffer to L2 the DSP processes the other L2 input buffer and then they switch. same for the output.

    This can give you much better performances with the DSP.

    Gabi 

  • Hello Gabi,

    I didn't want to bother you again but I can't find information about setting the L2 memory to be RAM instead of cache.

    I also couldn't find an appropriate C command to allocate memory within this L2 RAM. I did try Memory_alloc() which should allocate in whatever heap I choose, but fails when I select DSP_Internal_heap as the location.

    Thank you for all the help.

    -Roberto

  • Hi Roberto,

    In the file  ezsdk/component-sources/omx_xx_xx_xx_xx/src/ti/omx/build/dspsubsys.xs

    you can see that L2 is set to be 64K of cache, all other L2 can be used for placing your L2 buffers

    else if (soc == 'ti816x') {
    var device = 'TMS320TI816X';
    Build.platformTable['ti.platforms.generic:plat'] =
    {
    clockRate: 800.0,
    catalogName: 'ti.catalog.c6000',
    deviceName: device,
    regs: {l1DMode: "32k"},
    regs: {l1PMode: "32k"},
    regs: {l2Mode: "64k"},
    customMemoryMap: MemSegDefine.getMemSegmentDefinition(platFormMem),
    codeMemory:"DSP",
    dataMemory:"DSP",
    stackMemory:"DSP"
    };

    In the file ezsdk/component-sources/omx_xx_xx_xx_xx/src/ti/omx/build/MemSegmentDefinition.xs you can add something like this:

    memory[2] = ["DSP_L2",
    {
    name: "DSP_L2",
    base: 0x800000,
    len: 0x0030000,
    space: "code/data"
    }];

    and in the file ezsdk/component-sources/omx_xx_xx_xx_xx/examples/ti/omx/demos/dm81xx/AppMemSegPlacement.cfg you can write

    if (cfgArgs.coreName.match("DSP"))
    {
    /*
    * Do section mapping to memory regions
    */
    Program.sectMap[".vecs"] = "DSP";
    Program.sectMap[".cinit"] = "DSP";
    Program.sectMap[".pinit"] = "DSP";
    Program.sectMap[".args"] = "DSP";
    Program.sectMap[".switch"] = "DSP";
    Program.sectMap[".bss:eventList"] = "DSP";
    Program.sectMap[".const"] = "DSP";
    Program.sectMap[".fardata"] = "DSP";
    Program.sectMap[".data"] = "DSP";
    Program.sectMap[".sysmem"] = "DSP";
    Program.sectMap[".far"] = "DSP";
    Program.sectMap[".cio"] = "DSP";
    Program.sectMap[".systemHeap"] = "DSP";
    Program.sectMap[".stack"] = "DSP";
    Program.sectMap[".stackMemory"] = "DSP";
    Program.sectMap[".far:taskStackSection"] = "DSP";
    Program.sectMap[".plt"] = "DSP";
    Program.sectMap[".intHeap_0"] = "DSP";
    Program.sectMap[".intHeap_1"] = "DSP";
    Program.sectMap[".intHeap_2"] = "DSP";
    Program.sectMap["aacEncProgram"] = "DSP";
    Program.sectMap["My_l2_Buffers"] = "DSP_L2"; 
    }

    Now in your source files you can allocate buffers in L2 as follows:

    #pragma DATA_SECTION(Y, "My_l2_Buffers")
    #pragma DATA_ALIGN(My_Buf1,128)
    unsigned char My_Buf1[WIDTH*HEIGHT];

    Gabi


  • Gabi,

    Thank you for this complete outline! Where did you find how to do this? I'd like to better understand what is going on

    -Roberto

  • Hi,

    It was combination of previous knowledge with TI DSPs and trial and error. I am not sure this is the best\recommended\optimal way, but it worked for me.

    Gabi

  • From your outline I was able to get the Memory_alloc function to track my memory use at runtime, instead of allocating at compile time using Pragma.

    In ~/ezsdk/component-sources/omx_05_02_00_46/examples/ti/omx/demos/dm81xx/DspAppMain.cfg I added:

    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var heapMemParams2 = new HeapMem.Params;
    /* First allocation of memory for L2RAM */
    heapMemParams2.size = 0x00038000;   //Same as MemSegmentDefinition.xs size to use all of your L2 RAM
    heapMemParams2.sectionName = "My_l2_Buffers";
    var heap1 = HeapMem.create(heapMemParams2);
    Program.global.DSP_HEAPINT_MEM = heap1;
    Memory.Object__heap = heap1;

    Then in your dsp code:

    #include <xdc/std.h>
    #include <xdc/runtime/IHeap.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Memory.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/cfg/global.h>
    extern IHeap_Handle DSP_HEAPINT_MEM;

    char * MyBuffer = Memory_alloc((IHeap_Handle)DSP_HEAPINT_MEM, size, 128, NULL);

    -Roberto

  • Hi Roberto,

    I am facing a problem, when i am working with an OMX chain that doesn't contain VLPB my EDMA driver for A8 is working ok.
    When i am working with an OMX chain that contains VLPB that uses EDMA on the DSP, my A8 EDMA stop working.
    Have you encountered and solved such a problem in your work?

    Gabi 

  • Gabi,

    I haven't had a problem with using edma on both cores. My suspicion is that you are using edma a lot on the dsp, perhaps enough to use up all 100 dma slots? Or perhaps your addresses are null or not mapped to physical address, I'd print those. Also the size should be 128 aligned and the acnt should be less than 2^16. Most of this I'm sure you're aware of, just reiterating for others. As to it working for me, yes it does I use it on both dsp and arm to transfer 720*288 frames at 50fps.

    I'm not sure how you made the mechanics to transfer on arm but I used ioctl driver.

    -Roberto

  • Roberto,

    I am not doing intensive use with EDMA on the DSP side and i believe that all EDMA slots are divided hardly by the DSP and A8 such that A8 can't use DSP slots and the other way around, my addresses are not null and mapped to physical addresses, aligned to 128, the acnt is OK. It seems that there is some sort of memory contention between the DSP and the EDMA because i am using the same code in an OMX chain without DSP that performing data transfers fine on A8 side and when i am adding the VLPB on DSP to the OMX chain then the data is corrupted. I think i will open a new thread for this problem.

    Gabi

  • Gabi,

    You are correct in your train of thought that there may be contention. If the memory is being used by the DSP then the transfer will surely fail. You can test that the DMA is working by just allocating a small array and filling it up with simple data (ie. all 1's). After that, contention could be tested by copying a small simple amount, such as 128 bytes.

    Perhaps I have not done sufficient transfers on A8 side to have seen the problem as I just use it to make copies of the vlpb output buffer. I'd be interested in the thread if you make one as I will be adding more edma transfers A8 side soon and may be able to contribute more then.

    -Roberto

  • Gabi,

    in your original post you got an error with your first malloc. I believe your problem is due to not having called OMX_Init() before you try mallocing memory in a shared region. Before calling this function, the memory regions are not setup, so telling it to allocate memory in shared region 2 is gibberish to it.

    - Roberto