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.

how to define a symbol seen by arm compiler and linker?

Hello,

 

I have a code section (interrupt entry table), which start address should be a symbol that has to be known to the c-compiler (for setting the base register in normal c-code) , the assembler (for the interrupt handler to jump to the table) and the linker (for linking the table to the base address set in the c-code). I know how to define a symbol in a *.asm file, which could also be used in a *.c file. But the linker can't use that symbol in the linker.cmd file's SECTIONS directive to link the code section (the interrupt entry table) to the correct memory location.

Is there the possibility to define such symbol? If yes, in which file I have to define it (linker.cmd file or asm file)? Solving the problem is not essential for survival, but would save the trouble to change the start address in all files, if necessary. I use the TMS470 c-compiler v4.6 with CCS v4.1.3. Here's my source code to better illustrate my problem:

 

main.c

extern Uint32 eabaseaddress;    /* symbol is defined in the intvecs.asm file */

....

INTC_EABASE = eabaseaddress;   /* setting the EABASE address for the arm interrupt controller */

....

---------------------------------------------------------------------------------------------------

intvecs.asm

...

    .global eabaseaddress          /* make symbol seen by all other files */

...

eabaseaddress:

    .word 0x00006000    ; entry address of interrupt table

...

----------------------------------------------------------------------------------------------------

linker.cmd

...

SECTIONS

{

    .inttable > eabaseaddress     /* Linker doesn't know that symbol !!! */

...

}

 

Regards,

Matthias

  • The typical pattern is to define a set of memory ranges in the linker command file with the MEMORY directive.  Then, in the SECTIONS directive, you assign sections to those memory ranges with the syntax ...

    output_section > memory_range

    In the specific case of the interrupt vector table, a memory range is usually dedicated to it.  

    MEMORY {
       FOR_ISR : origin = 0x6000, length = 0x200 /* or whatever the correct length is */
       ...
    }
    
    SECTIONS
    {
       .inttable > FOR_ISR   /* only output section placed in FOR_ISR */
       ...
    }
    

    The symbols defined in the .inttable section will get the addresses, including the starting address, accordingly.  

    One more detail, in the C and assembly code you probably mean to write something like

    Uint32 *INTC_EABASE = &eabaseaddress;  // in C
    
        .global _eabaseaddress             // in asm
    

    Note the use of the leading underscore (which is not needed in EABI) and the ampersand.

    Thanks and regards,

    -George

  • Hello,

     

    thank you for your answer. I know the basics on how to write a linker.cmd file and my question was more to the effect on how to make addresses in the linker.cmd file variable (e.g. substitute an address by a symbol, which can be seen by the compiler / assembler?).

    Like in your example:

    MEMORY {
    FOR_ISR : origin = 0x6000, length = 0x200 /* or whatever the correct length is */
    ...
    }

    SECTIONS
    {
    .inttable > FOR_ISR /* only output section placed in FOR_ISR */
    ...
    }

    Is it possible to put the red parts in a symbol and refer to that symbol in the c and asm files?

    For example:

    for_isr = 0x6000;

    MEMORY {
    FOR_ISR : origin = for_isr, length = 0x200 /* or whatever the correct length is */
    ...
    }

    SECTIONS
    {
    .inttable > FOR_ISR /* only output section placed in FOR_ISR */
    ...
    }

    And in the c file I can use something like:

            INTC_EABASE = for_isr;

     

    Regards,

    Matthias

  • MW said:

    For example:

    for_isr = 0x6000;

    MEMORY {
    FOR_ISR : origin = for_isr, length = 0x200 /* or whatever the correct length is */
    ...
    }

    SECTIONS
    {
    .inttable > FOR_ISR /* only output section placed in FOR_ISR */
    ...
    }

    The above syntax will not work but you may be able to use the START operator for this purpose.

    For example, in the linker command file:

    #define ISR_BASE 0x6000

    MEMORY
    {  
        FOR_ISR : origin = ISR_BASE, length = 0x200
    }

    SECTIONS
    {
       .inttable : START(_start_of_inttable) {} > ISR_BASE
    }

    Then in the C code, reference it as:

    var = &start_of_inttable;

    More details on these linker operators are in Section 7.5.8.7 of the TMS470 Assembly Language Tools Users Guide.

  • MW said:
    MEMORY {
    FOR_ISR : origin = 0x6000, length = 0x200 /* or whatever the correct length is */
    ...
    }

    SECTIONS
    {
    .inttable > FOR_ISR /* only output section placed in FOR_ISR */
    ...
    }

     

    Is it possible to put the red parts in a symbol and refer to that symbol in the c and asm files?

    Would a preprocessor symbol do?  You could do something like this ...

    /* membase.h */
    #define MEMBASE 0x6000
    
    /* link command file excerpts */
    #include "membase.h"
    MEMORY {
       FOR_ISR : origin = MEMBASE, length = 0x200
       ...
    }
    

    You could include membase.h in your C code and asm code (via the .cdecls directive) as well.  Note the linker added preprocessing capability only in the most recent versions.

    Thanks and regards,

    -George

  • Hello,

     

    that was exactly what I needed. I've tried the "membase.h" solution and it worked with my linker version. Thank you!

     

    Unfortunately, I can't verify your answer (the link always leads to a page error).

     

    Regards