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.

TMS320C6678: Partition external memory to store program code

Part Number: TMS320C6678

Hi all,

I am trying to move some functions to external memory as my program is very big and the internal memory is not enough now. And the program used for eight cores may not be the same so I need eight partition of the external memory, each partition will be used for each core. I searched and there is one suggestion is to create eight build configuration with pre-define core ID, then use the user linker command file to put the code section of each core to one of eight different external memory segments. however this way is not suitable for me as my project require that each revision I can only have one project with one build configuration to create one bin file.

Is there any way that I can put code of each core to one of different external memory segments with only one project and one build configuration?

Thanks in advance,

Chanh 

  • Hi,

    As far as I know to use only one build You have to use a single image (same code) on all the cores, and each core will execute only a part of the code.

    This means that:
    1. cannot give the same name to two different routines designated to be executed on different core (you will get multiple defined symbols), but you automatically reuse the common code
    2. the logical addresses used by the code will be be the same for all the cores, so an variable allocated on the L2 SRAM will be automatically private for each core (if you use L2 as RAM), while any variable allocated on shared memory (MCSM or DDR) will be by default shared

    The first constraint can be address by carefully write the source code, while the logical data addresses overlaps problems depend on how you plan to organize you data, if you want to use L2 as memory or as cache and maybe come constrains imposed by the RTOS you use (SYS/BIOS?)

    In this scenario, You don't care to much on the code memory partition but you have to focus on the data memory partition and logical to physical address translation to allow every core to use same logical data address to access different physical data.

    If using SYS/BIOS, look at:
    processors.wiki.ti.com/.../BIOS_on_Multi-Core_singleimage application&tisearch=Search-EN
  • Hi Alberto,

    Thanks for your reply. I think I have not explained clearly about the situation.

    My project can have only one or multiple bin file run on 8 cores. Let's say:
    - Bin_file_1 contain Lib_A and Lib_B
    - Bin_file_2 contain Lib_A and Lib_C
    - Bin_file_3 contain Lib_A and Lib_D
    - etc...

    Lib_A will be common for all the bin files, and depends on situation, there is no rule for which bin file will be run on which core. And I only can maintain 1 project to build one bin file (e.g. project_1 to build Bin_file_1, Project_2 to build Bin_file_2, etc.)

    Now the problem is that my program is very big and the L2 memory is not enough, and there is a requirement that different bin file can use different revision of Lib_A so I plan to move some functions of Lib_A to a partition of external memory, and the partition have to be different for each core.

    Hence, do you have any suggestion on how I can put code sections of each core to one of different external memory segments with only one project and one build configuration?

    Thanks a lot,
    Chanh
  • Hi,

    So you want to have N builds, where N is the number of different exe and is not related to the executing core.

    Have you already considered the TI MAD utility (processors.wiki.ti.com/.../MAD_Utils_User_Guide)

    If you never execute the same exe on multiple cores at same time, you can define N partitions (in the linker file), one for each exe (not for each core) and each exe should be able to run on the core of your choice, that is in general is not required to build for a specific core.

    You can also use the same memory partition (that is logical address reserved for the code and also for the data mapped in shared memory) for all the exe but then you have to remap the logical addresses to N physical partition prior to load you core, so a run-time support is required by your loader.

    In this way you can run the same code on multiple core, but you have to pay attention when passing pointer to the logical addresses between cores

    For instance, suppose you define a logical partition at 0x80000000-0x80100000 (1M), then N physical partitions:
    0x80000000+N*0x00100000
    All exe link at logical addresses. Prior to execute the code You have to initialize an MPAX entry (see CorePac manual SPRUGW0) to remap from logical to physical, according to the core number. Your loader have to know how to move the logical program section to the physical one.

    How do you load the exe?
  • Hi Alberto,

    Yes, I have N program where the different is only on Lib_B, Lib_C (as in the above example), and each program will have several revisions. Depend on the application, the program run on each core could be the same or different.

    Mapping logical address to multiple physical address in which once core will reserve one physical address seems to be a direction for me. But since my number of programs is not limit so I refer to define 8 partitions of memory for 8 cores. How can I initialize an MPAX entry before the code execution? Do you mean I can achieve that using MAD tool? I am checking the MAD tool, if you have any suggestion or example please share to me.

    For my project, the bin file will be download to each DSP core using SRIO (depend on the application, it could be BIN_1 downloaded to all cores; or BIN_1 downloaded to core_0, BIN_5 downloaded to core_3, and so on). Is it what you ask about by "load the exe"?

    Thanks.
    Chanh
  • Hi,

    when I ask about the loader, I means how you copy the executable in the per-core memory.
    As a general pattern, for each core You have to:
    1. Set MPAX to the map from logical to physical for core N
    2. Load the code via SRIO
    3. start the slaves core and as first operation (in the slaves), set up the core MPAX register to the dedicated core partition

    To setup the MPAX for each core, you have to override the default entry point with a custom routine to:
    a. change the MPAX
    b. jump to the standard startup routine (c_int0)

    Note that you cannot use DirectIO to load the code, since the DirectIO always use physical address and bypass your MPAX mapping.
  • Hi Alberto,

    I am reviewing my program boot sequence now (since it is developed by another person). So far what I can see is that the program is loaded through SRIO. However, it seems that MPAX is done after the code is load (as the function to set up MPAX registers is call inside the main() function).

    Could you please advise more on how to override the default entry point with a custom routine to change the MPAX and jump to the standard startup routine (c_int0)? Sorry I am very new to this DSP.

    Thanks a lot.
    Chanh.
  • Hi,

    To override the entry point, first add linker option "--entry_point custom_boot". Since it will be the first routine to be executed, you have to setup a minimal C run-time support, that is the stack. Look at the boot.c files in the TI libc source file (included in CCS):

    extern void _c_int00(void);
    
    __asm("\t.global __TI_STACK_END");
    __asm("\t.global __TI_STATIC_BASE");
    
    void __interrupt custom_boot(void)
    {
       //Stack setup for EABI, from the TI _c_int00() source code
       __asm("\t   MVKL\t\t   __TI_STACK_END - 4, SP");
       __asm("\t   MVKH\t\t   __TI_STACK_END - 4, SP");
       __asm("\t   AND\t\t   ~7,SP,SP");               
       __asm("\t   MVKL\t\t   __TI_STATIC_BASE,DP");
       __asm("\t   MVKH\t\t   __TI_STATIC_BASE,DP");
    
      //remap logical to physical,using DNUM and hard-coded addresses or addresses defined in the linker command file
    .... _c_int00(); //Standard TI entry point }

    Since the C initialization routine has not been yet called, so you can use only the stack and it is not safe to use other code external to you boot compilation unit (function call) or constant data stored in the data segments. Anyway, it is possible to write an MPAX initialization code that only use values coded in your text segment (that is hard-coded integral literals).

    To understand and verify you code, I suggest you to prepare a little prototype for single core to test on the EVM and add a memcpy(physicial, logical, size_partition) before remapping in custom_boot(). libc memcpy() is not safe to use (depend on where it is located) so you should put the copy-code directly inline in custom_boot().

    Note that also in your boot loader you can use the same technique: instead of working on MPAX,  after each core load, copy the logical to the per-core physical.

  • Chanh,

    Sorry for the delayed response. Alberto thanks for providing your inputs on this topic.

    From what I understand from your explanation you have one project per exe (per core). This makes things simpler than in the case of a single project with different build configurations. In order to partition the memory, you can create a single linker command file where the entire memory space if partitioned between the 8 cores so that none of your DSP cores use memory regions that overlap with memory assigned to a different core. Use global addressed for DSP internal memories so that you can add them to the memory sections separately as well.
    The same applies to TI RTOS, you can create a custom platform configuration where the MSMC and DDR space is paritioned for all cores and each core only uses memory section assigned to it.

    MAD tools will be useful if you want to maintain single copy of the library between multiple core but adds significant amount complexity to the project as those tools have a complex build steps and the way the tool creates the images using parser and linker are not straight forward to understand. If you don`t mind maintaining multiple copies of the libraries then I would avoid use of this tool.

    Regards,
    Rahul
  • Hi Rahul,

    Thanks a lot for your reply.

    My project requires to maintain only one copy. Right now my solution will be configuring MPAX register at the early state of the program.

    MAD tools is powerful, but it is complicated and I am not familiar with it. I plan to study it to see if I can use it for my project in future, but I expect it may takes me some time.

    Regards,
    Chanh
  • Hi Alberto,

    Thanks a lot for your advice,

    I can change the entry point but it is not easy to configure the MPAX register at that time, and not easy to maintain in the future. Hence, instead I plan to configure MPAX at xdc.runtime.Startup so that I can use the structure and macro defined in CSL library. It seems to work for me.

    Regards.
    Chanh