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.

MCU-PLUS-SDK-AM273X: LAST() on c66 linker memory segment

Part Number: MCU-PLUS-SDK-AM273X

Hello,

I need to allocate heap memory during program runtime.
For that reason I use LAST() function in linker MEMORY section on c66 core. But when I define this for example:
DSS_L2:   ORIGIN = 0x800000 , LENGTH = 0x60000 LAST(last_dss_l2)
I get output 


line 58: error #10025-D: invalid memory attribute specifier: "last_dss_l2"
"../linker.cmd", line 58: error #10079-D: origin not specified for memory range LAST
"../linker.cmd", line 58: error #10080-D: length not specified for memory range LAST


The same exact code works perfectly fine on r5f. As far as I understand from compiler/linker documentation I can use LAST both for c66 and r5f, can't I?
Thank you in advance for response, Ivan K.

  • Documentation for the C6000 linker states the LAST operator is supported.  However, when I try it, I also see diagnostics similar to ...

    line 58: error #10025-D: invalid memory attribute specifier: "last_dss_l2"
    "../linker.cmd", line 58: error #10079-D: origin not specified for memory range LAST
    "../linker.cmd", line 58: error #10080-D: length not specified for memory range LAST

    So, I filed EXT_EP-10857 to have this investigated.  You are welcome to follow it with that link.

    Thanks and regards,

    -George

  • It turns out the documentation for the C6000 linker is incorrect.  It does not support the LAST operator.  This will be corrected in the documentation.  I apologize for the error.

    Thanks and regards,

    -George

  • Thank you for the answer. I managed to deal with it.  Also I have a problem with getting default heap avaliable memory. Can you help me with getting in my cpp code, during runtime,  to sys_free variable, which is defined in memory.c compiler src file on C66? 

    Regards, Ivan. 

  • I don't understand your question.  I hope some general background on dynamic memory is helpful.

    Please search the C6000 compiler manual for the sub-chapter titled Dynamic Memory Allocation.  It describes how things work for the RTS functions malloc, free, etc.  But the same documentation applies to the C++ functions new and delete.

    Thanks and regards,

    -George

  • Sorry for badly explained question. Basically, I need to rebuild both C6000 and Clang compiler's libraries and I can't deal with it. Can you help me or mention source, where I can find tutorial or something for both compilers? 

    Thanks in advance, Ivan.

  • To precise, I want to rebuild memory.c file and I know, that C6000 has mklib tool, but I can't understand what exactly lib i have to rebuild. Or should I rebuild all the libs with --all flag ( this takes a lot of time) . 

  • One possible solution is to make memory.c yet another source file in your project.  If you don't want to do that ...

    I can't understand what exactly lib i have to rebuild

    When you build your project the first time, the compiler automatically chooses the best RTS library based on the compiler options used to build the core source files in the project.  I presume you have already done that.  So, rebuild this particular library.  

    To understand the RTS library names, please search the C6000 compiler manual for the sub-chapter titled Library Naming Conventions.

    For tips on using mklib, please see this forum thread.

    Thanks and regards,

    -George

  • I have one more question concerning this topic. If LAST() is not supported by C6000 linker. Is there any other way to define custom heap in memory section and get it's runtime size and memory address. We need this to use dynamic memory allocation. Temporarily we have const heap size. Thank you for your answers, 
    Ivan

  • Is there any other way to define custom heap in memory section and get it's runtime size and memory address.

    Here are two techniques to consider.

    One ... Create a header file that is included in both the C source and the linker command file.  Something similar to ...

    /* memdefs.h */
    #define HEAP_ORIGIN 0x00200000
    #define HEAP_LENGTH 0x00002000

    The linker command file could have something similar to ...

    #include "memdefs.h"
    
    MEMORY
    {
        HEAP_MEMORY : origin = HEAP_ORIGIN, length = HEAP_LENGTH
        ...
    }
    
    SECTIONS
    {
        heap_section { . += HEAP_LENGTH; } > HEAP_MEMORY
        ...
    }

    Two ... Associate symbols with the heap section and refer to them from C code.  The linker command file could have something similar to ...

    SECTIONS
    {
        heap_section
        {
            ...
        } > MEMORY_RANGE_NAME, RUN_START(heap_origin), RUN_SIZE(heap_length)
    }

    To learn how to use the symbols heap_origin and heap_length from C code, please search the C6000 assembly tools manual for the sub-chapter titled Using Linker Symbols in C/C++ Applications.

    Thanks and regards,

    -George

  • Actually I tested those solutions. Neither solves our problem. Size of the heap is still const, we need to declare extra memory anyway and cannot allocate dynamically during the program runtime. 

    What we need is getting last linker allocated memory element / symbol and remained size at any point of a program runtime and allocate new symbols after linkage dynamically. 
    And we need to do this for both DSS_L2 and shared L3 independently.

    Thanks and regards, Ivan.

     

  • I don't think I understand your request.  Please provide a code example, or something similar, which demonstrates your desired solution.  Feel free to invent new syntax or tool features as needed.  When you do, please describe them in detail.

    Thanks and regards,

    -George

  • In ti examples there is this structure of memory
     


    Then there is generated debug.map 
    DSS_L2                00800000   00060000  00018ff1  0004700f  RWIX

    Is there a way to know start address of next free DSS_L2 memory block / space on C66 core during program runtime in a same way like LAST() works on r5f core .

    It turns out the documentation for the C6000 linker is incorrect.  It does not support the LAST operator

    LAST - optionally specifies a symbol that can be used at run-time to find the address of the last allocated byte in the memory
    range 

    We need this feature to allocate memory dynamically during program run. Since c66 does not supports this is there another way? 

  • Since c66 does not supports this is there another way? 

    Please see this forum thread.  It shows some other ways to solve this problem.  While they work, they are not convenient.  Which is why the LAST operator was added to the linker.  Unfortunately, this feature is not supported by the C6000 linker.

    Thanks and regards,

    -George

  • This worked out nicely, thank you.
    Another question. Can we have some MACRO defined in cmake to customize library data placement in memory.  Macro's should control what memory range should linker use ( RAM / ROM ) ?
    For example library_1 has HIGH_PRIO defined so the linker puts it to FAST_MEM and library_2 has LOW_PRIO defined and linker puts it to SLOW_MEM. 

    -Thank you for your responses, Ivan 

  • The linker command file supports a preprocessing feature similar to the one in the C/C++ compiler.  This includes the ability to define preprocessor names on the command line.  Here is an example of some lines from inside a SECTIONS directive ...

        library_code_section
        {
           --library=library_name.lib(.text)
        }
    #if   FROM_CMD_LINE == 10
            > MEMORY_RANGE_10
    #elif FROM_CMD_LINE == 20
            > MEMORY_RANGE_20
    #else
            #error FROM_CMD_LINE incorrectly defined
    #endif

    This creates an output section named library_code_section.  It is made up of all the .text input sections from the library library_name.lib.  It is allocated to a memory range that changes based on the command line.  The preprocessor name FROM_CMD_LINE must be defined on the command line similar to ...

    cl6x compiler_options -z --define=FROM_CMD_LINE=10 linker_options

    When FROM_CMD_LINE is 10, library_code_section is allocated to MEMORY_RANGE_10.  When FROM_CMD_LINE is 20, library_code_section is allocated to MEMORY_RANGE_20.  Otherwise, a diagnostic is issued.

    Thanks and regards,

    -George

  • I'm not sure if this is an option. We build a lot of libraries in project with this command ( debug example ) :

    cl6x.exe --compile_only --cpp_file=main.cpp -DCPU_TIC66xDSP -DCORE2 -mv6600 --abi=eabi -q -mi10 -mo -pden -pds=238 -pds=880 -pds1110 -g -DSOC_AM273X --c++14  -D_DEBUG -Ooff --output_file=main.cpp.obj

    And I'm curious if it is possible to add something to this command during compilation so linker could differ high_prio libraries and low prio libraries and put them automatically to needed memory addresses.

    Also i would not like to type --library=library_name.lib(.text) in linker to every of many libraries. 

    Thank you, Ivan.

  • This command ...

    cl6x.exe --compile_only --cpp_file=main.cpp -DCPU_TIC66xDSP -DCORE2 -mv6600 --abi=eabi -q -mi10 -mo -pden -pds=238 -pds=880 -pds1110 -g -DSOC_AM273X --c++14  -D_DEBUG -Ooff --output_file=main.cpp.obj

    ... does not create library.  It creates a single object file named main.cpp.obj.  So when you say ...

    We build a lot of libraries in project

    ... do you really mean you build a lot of object files?

    A library is a collection of multiple object files.  The command which creates a library is called the archiver, and it is named ar6x.  If you do not use that command, then you are not creating a library.

    Thanks and regards,

    -George

  • Yes we build libraries with:

    cl6x.exe --compile_only --cpp_file=c_ap_am273x_pin_muxing.cpp -DGIT_BRANCH_INFO=\""  --cmd_file=CMakeFiles/c_ap_am273x_pin_muxing.dir/includes_CXX.rsp -DCPU_TIC66xDSP -DCORE0 -mv6600 --abi=eabi -q -mi10 -mo -pden -pds=238 -pds=880 -pds1110 -g -DSOC_AM273X --c++14 -pm -o3 -mf3 --output_file=CMakeFiles\c_ap_am273x_pin_muxing.dir\c_ap_am273x_pin_muxing.cpp.obj

    Then we link it to main.cpp

    In previous project we had defines like this in cmake file:

    set(PLACE_CODE_AND_DATA_IN_FASTEST_MEMORY -section code=fast_prio1_code,alldata=fast_prio1_data

    Which recognized every
    add_definitions( ${PLACE_CODE_AND_DATA_IN_SLOWEST_MEMORY} ) during library build
    and associated it with some section ( fast_prio1_data )  -> then go to needed memory directive. 

    Moreover we were able to use:

    #define PRAGMA_DATA_PRIO_1          _Pragma("section(\"fast_prio1_data\")")

    and then use it in .cpp file

    Is there any way to make it work? 
  • Unfortunately, I do not know CMake, and I am unable to help you with those details.

    Regarding ...

    #define PRAGMA_DATA_PRIO_1          _Pragma("section(\"fast_prio1_data\")")

    The C6000 compiler supports some similar pragmas.  You may be able make them work in your code.  Please search the C6000 compiler manual for the sub-chapters titled The DATA_SECTION Pragma and The SET_CODE_SECTION and SET_DATA_SECTION Pragmas.

    Thanks and regards,

    -George