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.

Linking order issues when placing library functions in same section

Other Parts Discussed in Thread: TMS320F28069

I am using TMS320F28069. In my project I am using C runtime support library "rts2800_fpu32.lib" and "rts2800_fpu32_fast_supplement.lib" for faster FPU routines (sin, cos, atan2, ...). The linker knows to use this routines over the ones in "rts2800_fpu32.lib" because I've specified link order in project settings so that "rts2800_fpu32_fast_supplement.lib" is linked before "rts2800_fpu32.lib"

I am moving my code to run from FLASH, I am placing all my time critical code to "ramfuncs" section to load the code from FLASH to RAM and execute it from RAM for faster operation. As the FPU routines within "rts2800_fpu32_fast_supplement.lib" are in .text section, I am relocating them to ramfuncs within linker command file with following code:

ramfuncs: {
           rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<div_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<sqrt_f32.obj>(.text)
           *(ramfuncs)
}

This works all well and good. My troubles start when I also want to place integer division routine "l_div.obj" from "rts2800_fpu32.lib" to "ramfuncs" section. From what I can observe adding one line to linker command file:

ramfuncs: {
           rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<div_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
           rts2800_fpu32_fast_supplement.lib<sqrt_f32.obj>(.text)
           *(ramfuncs)
           rts2800_fpu32.lib<l_div.obj>(.text)
}

causes that linker does not take the linking order in consideration. When the project is compiled I can see in the .map file that sin, cos, div, sqrt and atan2 routines are linked from "rts2800_fpu32.lib2, and the linker issues warnings about missing sections:

"../cmd/2806x_lnk_RAM.cmd", line 72: warning #10068-D: no matching section rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)"

Even if I place "l_div.obj" in its own section by:

ramfuncs_rts: {
               rts2800_fpu32.lib<l_div.obj>(.text)
              }

the linker still links "rts2800_fpu32.lib" before "rts2800_fpu32_fast_supplement.lib".

I would like to know why is this happening and what is the solution?

  • I am unable to reproduce your results. Please show exactly how the linker is invoked. Also attach the linker command file to your next post. Add the extension .txt to it, or it will be rejected.

    Thanks and regards,

    -George

  • /****************************************************************
    * FILENAME:     2806x_lnk_FLASH.cmd
    * DESCRIPTION:  device linker command file 
    * AUTHOR:       Mitja Nemec
    *
    ****************************************************************/
    
    
    MEMORY
    {
    PAGE 0 :
        RESET_M     : origin = 0x000000,    length = 0x000002
    
        P_M0        : origin = 0x000050,    length = 0x0003B0     /* on-chip RAM block M0 */
        P_M1        : origin = 0x000400,    length = 0x000400     /* on-chip RAM block M1 */
    
        P_L78       : origin = 0x010000,    length = 0x004000     /* on-chip RAM block L1 */
       
        P_OTP       : origin = 0x3D7800,    length = 0x0003FA     /* on-chip OTP */
    
        P_FH        : origin = 0x3D8000,    length = 0x004000     /* on-chip FLASH */
        P_FG        : origin = 0x3DC000,    length = 0x004000     /* on-chip FLASH */
        P_FF        : origin = 0x3E0000,    length = 0x004000     /* on-chip FLASH */
        P_FE        : origin = 0x3E4000,    length = 0x004000     /* on-chip FLASH */   
        P_FD        : origin = 0x3E8000,    length = 0x004000     /* on-chip FLASH */
        P_FC        : origin = 0x3EC000,    length = 0x004000     /* on-chip FLASH */
        P_FB        : origin = 0x3F0000,    length = 0x004000     /* on-chip FLASH */
        P_FA        : origin = 0x3F4000,    length = 0x003F80     /* on-chip FLASH */
       
        CSM_RSVD    : origin = 0x3F7F80,    length = 0x000076     /* Part of FLASHA.  Program with all 0x0000 when CSM is in use. */
        RESET_F     : origin = 0x3F7FF6,    length = 0x000002     /* Part of FLASHA.  Used for "boot to Flash" bootloader mode. */
        PSWD        : origin = 0x3F7FF8,    length = 0x000008     /* Part of FLASHA.  CSM password locations in FLASHA */
    
        FPUTABLES   : origin = 0x3FD860,    length = 0x0006A0	  /* FPU Tables in Boot ROM */
        IQTABLES    : origin = 0x3FDF00,    length = 0x000B50     /* IQ Math Tables in Boot ROM */
        IQTABLES2   : origin = 0x3FEA50,    length = 0x00008C     /* IQ Math Tables in Boot ROM */
        IQTABLES3   : origin = 0x3FEADC,    length = 0x0000AA	  /* IQ Math Tables in Boot ROM */
    
        BOOTROM     : origin = 0x3FF3B0,    length = 0x000C10     /* Boot ROM */
        RESET       : origin = 0x3FFFC0,    length = 0x000002     /* part of boot ROM  */
        VECTORS     : origin = 0x3FFFC2,    length = 0x00003E     /* part of boot ROM  */
    
    PAGE 1 :
        D_M0_S      : origin = 0x000002,    length = 0x00004E     /* Part of M0, BOOT rom will use this for stack */
        D_M0        : origin = 0x000050,    length = 0x0003B0     /* on-chip RAM block M0 */
        D_M1        : origin = 0x000400,    length = 0x000400     /* on-chip RAM block M1 */
    
    	D_L06       : origin = 0x008000,    length = 0x008000     /* on-chip RAM block L0 */
    
        D_OTP       : origin = 0x3D7800,    length = 0x0003FA     /* on-chip OTP */
    
        D_FH        : origin = 0x3D8000,    length = 0x004000     /* on-chip FLASH */
        D_FG        : origin = 0x3DC000,    length = 0x004000     /* on-chip FLASH */
        D_FF        : origin = 0x3E0000,    length = 0x004000     /* on-chip FLASH */
        D_FE        : origin = 0x3E4000,    length = 0x004000     /* on-chip FLASH */   
        D_FD        : origin = 0x3E8000,    length = 0x004000     /* on-chip FLASH */
        D_FC        : origin = 0x3EC000,    length = 0x004000     /* on-chip FLASH */
        D_FB        : origin = 0x3F0000,    length = 0x004000     /* on-chip FLASH */
        D_FA        : origin = 0x3F4000,    length = 0x003F80     /* on-chip FLASH */
    }
    
    SECTIONS
    {
    /* VARIABLES */
        .bss: >         D_L06,           PAGE = 1
        .ebss: >        D_L06,           PAGE = 1
    
    /* CODE */
        .text: >        P_FD,           PAGE = 0
    
        ramfuncs:       {
                            rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<div_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sqrt_f32.obj>(.text)
    						rts2800_fpu32.lib<l_div.obj>(.text)
                            *(ramfuncs)
                        }
                        LOAD = P_FD,
                        RUN = P_L78,
                        LOAD_START(_RamfuncsLoadStart),
                        LOAD_SIZE(_RamfuncsLoadSize),
                        LOAD_END(_RamfuncsLoadEnd),
                        RUN_START(_RamfuncsRunStart),
                        RUN_SIZE(_RamfuncsRunSize),
                        RUN_END(_RamfuncsRunEnd),
                        PAGE = 0
    
    /* IQ MATH TABLES */
        IQmathTables: > IQTABLES,       PAGE = 0, type = NOLOAD
      
        IQmathTables2: >IQTABLES2,      PAGE = 0, TYPE = NOLOAD
        IQmathTables3: >IQTABLES3,      PAGE = 0, TYPE = NOLOAD
        FPUmathTables: >FPUTABLES,      PAGE = 0, TYPE = NOLOAD
    
    /* STACK */
        .stack: >       D_M0,
                        RUN_START(_stack_start),
                        RUN_END(_stack_end),       
                        PAGE = 1
                        
    /* HEAP */  
        .sysmem: >      D_L06,           PAGE = 1
        .esysmem: >     D_L06,           PAGE = 1
    
    /* CONSTANTS */
        .econst: >      D_FC,           PAGE = 1      
        .const: >       D_FC,           PAGE = 1
    
    /* STARTUP CODE */
        codestart >     RESET_F         PAGE = 0
        .reset: >       P_FD,           PAGE = 0
        .cinit: >       P_FD,           PAGE = 0
    
    /* COMPILER GENERATED CODE */
        .pinit: >       P_FD,           PAGE = 0
        .switch: >      P_FD,           PAGE = 0
    
    /* PASSWORDS */     
        csmpasswds: >   PSWD,           PAGE = 0, type = NOLOAD
        csm_rsvd: >     CSM_RSVD,       PAGE = 0, type = NOLOAD
    
    /* BOOT ROM INTERRUPT VECTORS */
        vectors: >      VECTORS,        PAGE = 0, TYPE = DSECT
    }
    
    Hi George,

    I've attached linker .cmd file. Linker is invoked with folowing swithces (copy/pasted form CCS:

    -v28 -mt -ml --vcu_support=vcu0 --cla_support=cla0 --float_support=fpu32 --fp_mode=relaxed --advice:performance=all -g --diag_wrap=off --display_error_number --issue_remarks --verbose_diagnostics --gen_func_subsections=on --c_src_interlist -z -m"Meritev THD napetosti.map" --stack_size=0x300 --warn_sections -i"C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.6/lib" -i"C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.6/include" --reread_libs --disable_auto_rts --verbose_diagnostics --diag_wrap=off --display_error_number --issue_remarks --xml_link_info="Meritev THD napetosti_linkInfo.xml" --rom_model

    Linking order was set within CCS project settings (BTW why is this not the part of linker settings?)

    If I add also the .cmd file in the linking order setinhs like this I don't have any issues:

    But if I place tha .cmd file at the top of the linking order I get following errors:

    "../cmd/2806x_lnk_FLASH.cmd", line 72: error #10008-D: cannot find file "rts2800_fpu32_fast_supplement.lib"
    rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)

    I thought I understand the linking process, but I clearly need some tutoring. So my questions are:

    1. Why do I have this issue, what is causing it?

    2. Why the solution works?

    3. Why do I get linking error when .cmd file is the first to link?

    Thank you for your support 

  • I apologize, but I remain unable to reproduce your results.  I'd appreciate if you would submit the CCS project.  Please see this post for the details.

    Thanks and regards,

    -George

  • Thank you for your support. I clearly am doing something wrong, probably in exotic way, so I would like to know what it is.

    The project is attached

    Best regards, MitjaExported_project.zip

  • Your goal is so that these lines from the key link command file ...

        ramfuncs:       {
                            rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<div_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sqrt_f32.obj>(.text)
                            rts2800_fpu32.lib<l_div.obj>(.text)
                            *(ramfuncs)
                        }
    

    ... mean those functions from those libraries go into the ramfuncs output section, and not elsewhere.  The key bit of documentation here is the section titled Exhaustively Read and Search Libraries in the C2000 assembly tools manual.  Focus on the sentence about how the linker reads libraries in the order they are seen on the command line or in a command file.  For you to get the effect you seek, linker needs to encounter rts2800_fpu32_fast_supplement.lib first.  This needs to be true whether it is on the command line or inside a command file.  That's why the linker order rts2800_fpu32_fast_supplement.lib, the command file, rts2800_fpu32.lib works.  You could also have the command file listed first, so along as you don't change the order of the lines for the ramfuncs output section shown above.

    Another key option you use is --reread_libs.  As the documentation describes, this means the libraries can be referred back to by object files that occur later in the linker invocation.  While it makes no difference in this specific case, you should strongly consider using --priority instead of --reread_libs.  Suppose there is reference to the function atan2 from within rts2800_fpu32.lib. (There isn't.  But pretend there is.) With --reread_libs, that gets resolved from rts2800_fpu32.lib.  With --priority, it gets resolved from the first library seen rts2800_fpu32_fast_supplement.lib.  That's probably what you want.

    Thanks and regards,

    -George

  • Hi George,

    I understand the principle behind it. I don't have clear picture who or what sets the linking order within CCS?

    From reading C2000 assembly tools manual i think it is the order of "--library=..." options. I assume this is the reason why does the CCS have the option to move up/down the specified libraries under linker options. But why does the CCS also have the linking order tab under the build options? I'd imagine because you can also specify the order for processing .cmd files and other files. But which of these two ways takes effect when CCS is building the command line call to the linker? What if you specify the order under the build options, but you don't include the libraries under linker options? Shouldn't the tab be moved under linker options?

    It seems that my main beef is with CCS and not really with CGT.

    Thanks for the help.
  • Mitja Nemec said:
    It seems that my main beef is with CCS and not really with CGT.

    Are you using CCS 6.1.3?

    The reason is that there is the sticky thread *** CRITICAL **** Do NOT use CCS v6.1.3 on the C2000 forum, which details an issue with CCS 6.1.3 not following the correct link order.

  • Hi Chester,

    Yup, this might be the reason. I haven't seen the stick thread as it is posted under "InstaSPIN Motor Solutions Forum" and I regularly monitor only "C2000 32-bit Microcontrollers Forum", "TI C/C++ Compiler - Forum" and "Code Composer Forum".

    Thanks for the notice

  • I don't think the CCS 6.1.3 problem is related.  That is an issue with how CCS passes on the project build settings to the linker, and not a problem with the linker itself.  The issue in this thread is related only to the linker, and not CCS.

    Thanks and regards,

    -George

  • I agree with George that the issue in this thread is not related to the CCS 6.1.3 problem, and is only related to the linker and the order in which files are processed by the linker. 

    In CCS, there are two areas where ordering comes into play. If files are directly added/linked to the CCS project (these can be libraries, .cmd files etc), they appear on the command line just like all the object files and it is their ordering that can be controlled via the "Link Order" tab. 

    Alternately, they can be added to the --library option under Linker File Search Path, and the ordering there can be controlled via the Up/Down arrows. These are just two different ways of passing files to the linker.

    In this particular use-case, if you place the .cmd file at the top of the linking order, it is encountered first, and that at point, it does not yet know where to locate rts2800_fpu32_fast_supplement.lib that is referenced in the .cmd file. In this case, if you add the library path ${PROJECT_ROOT}/lib to the --search_path option, that will also get rid of the linker error.