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.

reading CPU memory map

Other Parts Discussed in Thread: TMS320C6678

Hi Guys,

I have a RTSC project and I want to use the memory protection modules of the C6678 to protect my program code from an unwanted access.

To achieve that, I am looking for a way to read the CPU memory map, which is defined in the target platform (e.g. ti.platform.evm6678), inside of my C/C++ Code.

I want to be able to know the memory map setup in my C/C++ Code so that I can configure the memory Protection module according to this mapping. But I don't want to manually create 2 seperate memory maps (one for linker, one for C/C++ Code) since this could easily lead to inconsistency.

Is there any way for a C/C++ Access to variables in the .cfg File? Or do you have any other ideas how I could achieve this?

Regards, Fabian

  • Fabian,

    Yes, you can access global variables defined in your config file.

    However, passing global handles to statically created objects to the application is the main use case for this feature:

        Program.global.myTask = Task.create('&myTaskFunc', myTaskParams);

    The global Task handle 'myTask' is passed to the application by including <xdc/cfg/global.h>:

        #include <xdc/cfg/global.h>

    While a globally accessible array of memory sections defined in your config file would be ideal, as far as I know, the 'Progam.global' mechanism does not support definiing arrays of ANY type.

    However, you can define a character string:

        Program.global.myString = "This is a string defined in my config file.";

    And therefore, you could construct a string that contains the memory regions defined in your platform.

    Something like the following untested config script code might be coerced into working:

    var memmap = Program.cpu.memoryMap;
    var memString = "";

    /* Find SDRAM in memory map                                                     */
    for (var i=0; i < memmap.length; i++) {
        memString += (memmap[i].base + " " + memmap[i].len + ", ");
    }

    Program.global.myMemMap = memString;
    I think the resulting char *myMemMap would point to a string of comma separated hex tuples ie: "0x00000000 0x000010000, 0x20000000 0x00002000, " etc.
    You could then parse myMemMap in your C code to obtain the platform memory regions.
    Alan
  • Fabian,

    A colleague just suggest that if you already know the names of the memory regions, and you simply want to pass the base and lengths of them to your C code, you simply define global variables (that actually get translated into #defines) with familiar names:

    Program.global.START_IRAM = 0x40000;
    Program.global.SIZE_IRAM = 0x1000;
    Or, if you don't know the base and length of the regions, you could parse the Program.cpu.memoryMap (as in my example) looking for matching region names and assign global variables with the values:
     if (memmap[i].name == "IRAM") {
    Program.global.START_IRAM = memmap[i].base;
    Program.global.SIZE_IRAM = memmap[i].len;
    }
    Alan
  • Hi, thanks for the suggestions. But I think this method is not very useful for several reasons.

    • I need to know the names or the ranges of my memory setup (which is stored in the platform file) when I write my .cfg fiel
    • This could leed to severe errors if the platform is changed
    • The handling of the generated variables is terrible, since there I cannot use any structs or arrays
    • This requires my C-Code to have certain knowledge of the memory setup (e.g. number of available memories, name of generated variables,...)

    With all this problems I don't think this is an appropriate method to achieve this.

    I found out that the memory setupt is stored in the Platform.xdc file in the platform folder.

    I have written myself a Parser-Program which reads this file and generates a C++-Header for my final DSP-Application. The generated output basically consists of a simple struct array defining all memory sections in a C-readable way.

    The Parser program could be started using the PreBuild.bat scripts of CCS. Here you can also provide the Path to the platform.xdc file

    Thus it is guaranteed that all files are up-to-date.

    If anybody is interested I could provide the parser here.

    Regards Fabian

  • Fabian,
    it's great if your solution is working for you. But I have to note that parsing Platform.xdc file is giving you only the initial content of the external part of the memory map. Platform.xdc for evm6678 contains only the spec for DDR3. The rest of the memory map is in the file TMS320C6678, in the package ti.catalog.c6000. Even if you parse the additional files, the memory layout can change for various reasons during the configuration step, for example to take into account cache settings.

    It can happen that for your configuration there are no changes, and your parser gives you the same memory layout as the one in the linker command script, but in general that's not the case.

    There are alternative solutions that would allow you to generate the full and correct memory map in C-readable array, but that would require you to have your own copy of the platform you are using, where you would have to add some additional code to generate a C++ header. If you want to try to work on your own platform, I can help you along the way.

  • Hi Sasha,

    sounds great! Actually I'm working on my own custom platform file. So that's probably the reason why the memory layout I parse is correct.

    It would be great if you can provide me with some information about how to create a good custom platform!

    My main intention for creating my own custom platform is, that I want to separate the actual physical RAM in several "virtual" memory spaces. With these spaces I want to use the Memory Protection features of the C6678 to protect Code and Constants and Code execution and to separate the memory spaces of different Cores, so that they disturb each other.

    Perhaps you even have another idea how I could achieve this, but for now separating the Memory in the platform file was my only idea.

    Thanks, Regards

    Fabian

  • There are two basic solutions for separating memory spaces on boards with multiple homogeneous cores. One solution is to use the Platform Wizard and then create a separate platform for each core. Then, when you build for a specific core, you have to choose the right platform in the RTSC tab of your CCS project. There are already threads that describe that solution in more details. Here is one of these threads. If you only need to split up memory, and you don't really want to write any XDCscript code, this is the way to go. The disadvantage is that you have to maintain multiple platform packages.

    In your case, you are not only splitting up the memory but you'll have to write some XDCscript code to have the memory layout available at runtime, so you need an alternative solution. The best way is to start from an existing platform, and you probably already did that. Have you started from evm6678?
    If you did, you'll notice the file Platform.xs. We should be able to limit the changes to this file only. In that file, there is a function instance$meta$init, whose first parameter is 'name'. That parameter is set to a platform instance name that you pass in the RTSC tab of your CCS project. Let's say your platform package is myplatform.c6678. If you set the platform name in the RTSC tab to myplatform.c6678:core0, the parameter 'name' wil be set to 'core0'. If you set the platform name to myplatform.c6678, 'name' becomes and empty string. That's how you will define which CCS project is built for which core. 

    Now before I go to far with it, can you tell me more what have you done by now and if you are already familiar with some of these concepts?

  • Hi Sasha,

    I have actually no experience with XDC scripts. I just used the Platform Wizard and created a platform, imported the settings form evm6678 and split up the memory sections for my use case.

    For my application I don't want to use multiple platforms/projects. I prefer to have only one single project to handle and thus having only one single image to load.

    I have read the articles about application images for multi-core devices from: http://processors.wiki.ti.com/index.php/Using_DSP/BIOS_on_Multi-Core_DSP_Devices

    My plan is to make a shared memory section for code and constant data for all cores, one shared section for "shared Variables" and one private Data section for private variables(all other variables). In order to avoid adjusting too much of my code for the multi-core (e.g. duplicating private variables for each core), I want to use the address remapping feature of the XMC, to map the private data to different segments in physical memory, while the "virtual" address, which the CorePac sees is identical for all Cores. I plan to use constructs like this to separate private data inside the MSMC:

        // Private data
        mpaxh[3].segSize = MPAX_SEGSIZE_256KB;
        mpaxh[3].bAddr = XMC_BADDR_MAKE(0x0C200000);
        mpaxl[3].rAddr = XMC_RADDR_MAKE(0x00C20000+coreNum*0x4000) ;

    This is where I need to know the memory mapping in my DSP program to configure the XMC correctly.

    Back to the XDCscripts: I had a look at my Platform.xs file but it looks totaly different from the one of the evm6678 (I have attached my platform folder to this post).

    Regards Fabian

    test2.rar
  • Fabian,
    I am not familiar with CorePac and XMC, but the basic question is whether you link only once and somehow when you load that single image to different cores, you use XMC to remap one common memory layout into different memory layouts for each core? If that's the case, then I misunderstood your post when you said "My main intention for creating my own custom platform is, that I want to separate the actual physical RAM in several 'virtual' memory spaces." I thought you wanted to do the separation at the config time, but now I think you are doing the separation in your C code. If that's correct then you need something different from a platform handling multiple memory layouts.
    If you are linking multiple times, then I am not sure how would you do that with one project and one single image.

    If your case is the first one and you are linking only once, then you can just replace the function getExeContext() in Platform.xs in your platform package:

    function getExeContext(prog)
    {
        var cont = this.$module.CPU.getExeContext(prog);
        var tplt = xdc.loadTemplate("ti/platforms/evm6748/cmem.xdt");
        tplt.genFile("new.c", cont.memoryMap);
        return (cont);
    }

    and add a file cmem.xdt with the following content to that same package:

    struct mem {
        unsigned base;
        unsigned size;
    } memArray[] = {
    %for (var entry in this) {
        `this[entry].base`, `this[entry].len`
    %}
    };

    You'll need to change the name of the file in xdc.loadTemplate() call with the name of the directory where your custom platform is located, and you also may want to specify the full path and a different name for the generated file that I simply named "new.c". If that's what you need, we can workout details that I didn't bother with right now.

  • Thanks for the answer.

    Sorry for the confusion about my intentions. I actually want to link only once and do separation in my C code, because as you said I don't see a way how to achieve the separation at config time with only one project.

    My text about the custom platform was a little bit confusing, I know. Perhaps I can make it clear with an example:

    I have a 8-Core DSP with 512 MegaByte of shared Memory. Now I want to make a single image application which runs on it without having the cores causing conflicts due to accesses to the same memory location.

    I create a custom platform with only 64 MegaByte of shared Memory and link the application to this "virtual memory"

    I use the Address remapping feature of the Memory Controller to shift the address of each core e.g.:

    • Core 0: works on physical address 0x00000000 - 0x03FFFFFF
    • Core 1: works on physical address 0x04000000 - 0x07FFFFFF
    • Core 7: works on physical address 0x1C000000 - 0x1FFFFFFF

    But still every Core works on its logical address space 0x00000000 - 0x03FFFFFF, so each Core could run with the same executable image.

    For configuring the Memory Controller I need to know the address and size of my "virtual memory" as specified in the platform.

    I hope this example make things clearer.

    The suggestion you made is exactly what I'm looking for. I tried it but I cam across several problems:

    • When I wanted to change the memory layout using the Platform wizzard (RTSC-Tools -> Platform -> Edit) it overwrites my changes to Platform.xs
    • When I try to change the memory layout manually, by editing the Platform.xdc file the changes do not apply, when build my project which is based on that platform. How do I modify the memory layout correctly without the Platform Wizzard?
    • The .c-file is generated correctly when I build my project, but it seems that the generated file does not get build/included in the project. No corresponding .obj file is generated and the linker does not find the memArray symbol

    Would be great if you could help me along with this further. You provided great support so far.

    Thanks Fabian

  • Ok, we are getting somewhere. My previous post wasn't very detailed because I wanted to find out first if I am on the right track. Now, we can fix the details.
    You are making changes to the platform that are out of the scope of the Platform Wizard. You'll have to use xdc command tools now to get your changes in Platform.xdc and Platform.xs recognized. So, first make the required changes in Platform.xdc and Platform.xs. Then, open a Windows command prompt and go to the directory that contains Platform.xdc and Platform.xs files for your platform. Then, run the following command:
    C:/ti/xdctools_3_24_03_33/xdc

    I am assuming that you are using XDCtools 3.24.03.33 installed in the directory ti. Please replace the path with the actual path for the XDCtools installation that you are using. This command should finish without errors and that's all you need to do to rebuild your platform, and keep both the changes in Platform.xdc and the new code in Platform.xs. You can keep repeating this build process (edit Platform.xdc, run xdc command) until you get the right memory layout.

    I don't know "the right way" of adding a generated file to the build, but I would try first just adding an existing version of new.c (if you followed the naming I used) to the project, right-click on project and then Add Files ... In the process of configuring your project, that file will be rebuilt, but there is enough steps that happen between rebuilding new.c and the moment when that file is compiled that realistically you shouldn't have to worry about any race conditions.
    Try these recommendations and let me know how it goes.

  • Thanks the xdc Command works

    Regards Fabian