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.

Using shared memory with IPC and SYS/BIOS

Other Parts Discussed in Thread: SYSBIOS, CC2650

Hello,

I've some questions of the usage of shared memory. My system setup is as follows:
-I want to use shared memory with static allocation (e.g. a struct or variable)
-I'm using a RTSC cfg file
-I'm already using IPC and SYS/BIOS

I've already declared a Shared memory region, see below. The purpose is for example to use one variable on each core. The variable is not accessed parallel from the cores, ONLY one after the other. As an example, I want to test doing some stuff over all cores like pipelining:

Processing Variable on CORE1 -> IPC-Notify to CORE2 -> Processing Variable on CORE2 -> ... -> and so on.

So I think I just have to place the variable in the shared memory (and be careful on this entry because it's used for IPC-stuff)?
Or are there better ways for this issue (e.g. place a new memory section into DDR3 or MSMCSRAM)?

How can I place the variable into shared memory? Is it the same as for a memory section (like this:
#pragma DATA_SECTION(variable, "Data_section")
uint32_t variable;

Using a static global variable it only works to modify the variable on CORE0, the modifications on other CORE's are not seen (of course I think due to every CORE having its own local copy of the variable?).

Thanks for help on this topic,
Best Regards,
Bernd

// Shared memory
var SHAREDMEM           = 0x0C000000;
var SHAREDMEMSIZE       = 0x00200000;

var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
SharedRegion.setEntryMeta(0,
    { base: SHAREDMEM,
      len:  SHAREDMEMSIZE,
      ownerProcId: 0,
      isValid: true,
      name: "DDR2_RAM",
    });

  • Hi,

    Lots of ways to do this. You could just allocate a block of memory out of the SharedRegion0's heap. Then in the notify, pass the address of that memory (with necessary translations if needed...I'm not  sure which device you are using).

    Are you trying to use a single .out on all cores (assuming it is a homogeneous system)? If so, you could also put the global array in a data section that is placed in shared memory. Then again, as you mentioned, use Notify to give ownership.

    Which method would you prefer?

    Todd

  • Hello Todd,

    thanks for your reply. As I try to make the project as simple as possible, I use one single .out for all cores for a homogenous system.

    According to the thread http://e2e.ti.com/support/embedded/bios/f/355/t/123986.aspx#442601 and your proposal I just placed the variable into one data section in MSMCSRAM  and modified it with several cores -> everything is fine. Placing it in DDR3, it doesn't work (I think only in MSMCSRAM a global addressing for every core is possible).

    I still have some further questions:
    -How can I place a memory section in my cfg file in the Shared Memory created like mentioned in the post above? I think I have seen something like Program.sectMap["Shared_section"].loadSegment = "SHAREDMEM:DDR2_RAM", but I'm not sure and it doesn't link.
    -What's the difference of placing a variable in MSMCSRAM or a shared memory (except of the size that I can define in the shared memory region if 4 MB is not enough)?
    -May I consider something about caching? I didn't thought so, but in the other thread (see above) it was mentioned.

    Best Regards,
    Bernd

  • Bernd,

    What device is this on?

    Here is an example for evm6472 (which has SL2RAM, LL2RAM and DDR2 memory segments).

    In the .cfg file, I place the new memory section into DDR2.

    Program.sectMap[".mysharedsection"] = "DDR2";

    In the .c file, I put the array "variable" into that section.

    #pragma DATA_SECTION(variable, "mysharedsection")
    Char variable[128];


    If you have cache enabled, you definitely have to worry about cache coherency. Assuming core0 "owns" the memory initially (e.g. initializes it), before it gives ownership to another core via a Notify, it should do a Cache_wbInv on the memory. This forces the contents of the cache to be written to the shared memory (DDR2 in my example). The next core should do a Cache_inv on that memory before it accesses it since it might have stale data in the cache for this address. There are some tricks you can do with the cache to improve performance, but if you follow this model, it will work. You need to be careful with the size of the memory also since cache commands act on a cache line. So be careful with sizes (should be a multiple of a cache line) and alignment (needs to be on a cache line boundary).

    FYI: MessageQ handles all of this for you.

    Todd

  • Hello Todd,

    1) I'm working with a TMS320C6678-EVM. Placing a variable into a memory section is no problem, but for a shared memory it doesn't work (see example below).

    2) I don't have to recreate something for caches if it already exists, e.g. in MessageQ; I just don't know how much is the overhead by using it. I want to get a real good performance and don't have much overhead for framework. So I have a lot of possibilities, e.g. it's better to use MessageQ or just disable caching in the Shared Memory region? Or anyway may it be the best to use Notify and care about the cache?

    What's your opinion? I know the concepts, but I'm not able to give a ranking due to performance and overhead.

    Thanks for your help,
    Best Regards,
    Bernd

    Example for Shared Memory:

    var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
    SharedRegion.setEntryMeta(0,
        { base: SHAREDMEM,
          len:  SHAREDMEMSIZE,
          ownerProcId: 0,
          isValid: true,
          name: "DDR2_RAM",
        });
    Program.sectMap["Shared_section"] = "DDR2_RAM";

    #pragma DATA_SECTION(uiTestMem, "Shared_section")
    uint32_t uiTestMem = 0;


    Compiling this one, I get the following errors:

    "./configPkg/linker.cmd", line 312: warning #10097: memory range not found:
       DDR2_RAM on page 0
    "./configPkg/linker.cmd", line 312: error #10265: no valid memory range(NULL)
       available for placement of "Shared_section"
    "./configPkg/linker.cmd", line 312: error #10099-D: run placement fails for
       object "Shared_section", size 0x14 (page 0)

  • Bernd,

    "DDR2_RAM" is the name of an Ipc SharedRegion memory block. It is not a "memory segment" that the linker knows about.

    MessageQ handles lots of things for you, but there is a learning curve. There is a performance impact since it has more functionality (there are no lunches!).

    Disabling the cache for a specific region might be fine especially if you are only reading and writing to a small block occasionally (cache does not help as much with this). However, I don't mean to scare you off from dealing with the cache coherency, especially in a relatively straightforward usage you are planning. You control the size of the block of memory, so make it a multiple of the cache line size. You can control the alignment, so make sure it is aligned on a cache line. Call Cache_wbInv on the memory before you notify the other core that the data is ready. On the notified core, make sure to call Cache_inv on the memory before you access any of it.

    Todd

  • Hello Todd,

    sorry, I have to ask a little bit more specific on those topics as I'm not sure if I've understood everything.

    1) Using a shared region
    I understand that the SharedRegion called DDR2_RAM is a memory block in an Ipc SharedRegion. But how can I use it for global variables like a memory section e.g. MSMCSRAM (which lies in the same address range), by the way how can I place a memory section in this "shared" memory block? Or is a sharedRegion not intended to be used for global variables as instead just for IPC stuff? Because also in the UI for the cfg file in CCS, the shared Region can't be seen neither as a memory segment or a section (what is clear) nor anywhere else...

    2) Disable / Enable Cache with difference in SharedRegion or MSMCSRAM
    -Which Cache-functions I have to use? I've found one header in xdc/runtime/knl and another one in ti/sysbios/family/c66...
    -Leaving point 1 beside and assuming I only use MSMCSRAM, (how) can I disable the cache (as the function cache_disable don't offer an appropriate type for this region)?
    -If using the functions from xdc, only a pointer and a length is needed which I can provide. But I'm not sure if this is the right way. Is there any example about this cache considerations?
    -Last how will I work with if have a section created in a sharedRegion? There I just can disable the cache at creation (that's clear) and use the functions from xdc?

    Thanks for your help,
    Best Regards,
    Bernd

  • Bernd,

    In regards to the first question...
    If you look in the mapfile, you'll see that the SharedRegion is really just a memory section, whose contents are managed by Ipc. For example (from an evm6472 Ipc example)

    ti.sdo.ipc.SharedRegion_0
    *          0    00200000    00048000     NOLOAD SECTION
                      00200000    00048000     --HOLE--

    It does provide a heap (SharedRegion_getHeap). This heap can be used to allocate memory during runtime from the SharedRegion.

    In regards to your second question...
    There are actually three places Cache calls exist

    1. ti/sysbios/hal/Cache module. For applications that are using SYS/BIOS, this is the standard module to use.

    2. ti/sysbios/family/XXX/Cache. This is the device family specific code. The ti/sysbios/hal/Cache module actually calls into these modules. For portability to other devices we recommend that users us the ti/sysbios/hal/Cache module instead of the device specific one. The exception is on some devices the family Cache module has extended capabilities that are not present in the sysbios/hal/Cache module (e.g. MAR bit management)..

    3. xdc/runtime/knl/Cache. This is a generic Cache module for XDC users. If SYS/BIOS is being used, the ti/sysbios/hal/Cache module is really used. Note: xdc/runtime is OS independent. So if your code is going to run on SYS/BIOS and non-SYS/BIOS operating systems, you should use xdc/runtime/knl/Cache.

    To enable/disable cache with the family specific Cache module (look under Sys/BIOS->Target Specific Support in the Available Products).

    To avoid confusion, do not mix and match different modules (e.g. use a combination of three Cache modules). This is possible, but you need to use the long names (e.g. ti_sysbios_hal_Cache_wb instead of Cache_wb).

    Todd

  • Hello Todd,

    thanks for your detailed answers, now I think I've understood everything.

    Best Regards,
    Bernd

  • Hi,

    I have a similiar problem too. I am using the CC6657 platform. I am developing two different tasks (one in each core) and they are supoosed to be sequential in the sense that the first one flush data to a buffer and the second one read data from that buffer. I am using as a baseline the example of Notify

    One of the ideas I got after reading the thread is to pass a pointer to the DDR3 memory in which I store the data through the callback function of the event as an argument. First question, is it possible to add an extra argument to this function?.

    The procedure should be in this way. The first task process data, write the data in the buffer. This buffer is stored in the DD3, so I allocate static buffer in the DDR3 through a pragma directive in the .c code and in the .cfg file:

    Core 0

    In .c code

    #pragma DATA_SECTION(bufA,".ExchangeBuffer");

    #pragma DATA_SECTION(bufB,".ExchangeBuffer");

    char *bufA, *bufB;

    In .cfg file

    Program.sectMap[".ExchangeBuffer"] = "DDR3";

    Core 1

    void cbFxn(UInt16 procId, UInt16 lineId,UInt32 eventId, UArg arg, UInt32 payload, char *bufA,char *bufB)

    Is it correct?

    Javier

  • Hello Javier,

    sorry for my late response, I was out of office. I repeat your question just to verify I understood your needs correctly:

    -you place some data in the DDR3
    -one core processes this data
    -another core should be triggered if core one has finished and should do something else with this data

    If this is correct, I've implemented an approach with a minimum overhead (because after timing measurements, the Notify examples needs some time to trigger other cores...):

    -Put the data array on a fix place in the DDR
          -> you can use the #pragma LOCATION: it will bound the array to a fix address
          -> disable caching of the address above with CACHE_disableCaching(Index); index is 128 for address
               0x80000000 and is incremented over whole DDR3 until 144 (have a look into documentation)
    -Setup a simple and fast IPC-routine to trigger another core (see attachment: 2630.Example IPC.txt)

    With this setup, you're able to share data between cores and process common data without many overhead.

    Regards,
    Bernd

  • Hello Todd,
    I am speaking in regards to cc2650 launchpad and TI-RTOS.I tried to combine aspects of heart rate and project zero in the same project.

    The project zero was being used to toggle LEDs through an android Application where it was also storing the log of the time and mobile number which toggled the led.

    I wanted to transmit this stored log, so i tried to combined the heart rate with my project zero.

    If I define 2 tasks in a same project, for example two separate functions for Project Zero and Heart Rate, can I share memory between the two functions? Right now I am defining all the functions in the same task.

    If the memory sharing is not possible, is it possible to define two separate tasks for project zero and heart rate in the same project and use the task switch option, if any , to get the cc2650launchpad to transmit the datalog to the smartphone. Essentially, the heart rate task fxn will be used as a transmitter. Please let me know your views on this. Sorry to trouble you.

    I understand that my end application might require memory sharing between these two functions since task 1 will store the log and task 2 will transmit it . But I can't wrap my head around how to do it.

    Please Help.

    Regards,
    Keyshav
  • Can you open a new thread as your question does not relate to this one.

    Todd