1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

specifying a memory location for global variable

Discussion in 'Embedded' started by alb, Mar 13, 2012.

  1. alb

    alb Guest

    Hi everyone,

    is there a way to specify either in assembler or C where a global
    variable should be located in the memory? (it's an ADSP21020).

    The reason for this is that, in the system I'm using, the protected area
    of the flash contains the runtime header which reference to a symbol
    called ___lib_int_table (where the address for interrupt service
    routines will be placed). This symbol was put by the linker at the
    beginning of the data memory at the time the program was built, but now
    that I am building a new program, which has to use the same runtime
    header, the only way to have the ___lib_int_table located in the same
    position is to follow a specific order during the linking phase,
    otherwise everything is screwed up.

    Since I don't want to rely on this particularly fragile approach I
    wanted to nail down the location once forever, since is not going to change.

    I know that there are C language extension for the g21k compiler which
    may specify whether we want to have a variable in the data memory or the
    program memory, but I have not found any reference for locating a global
    variable in a fixed memory location.

    Any suggestion is appreciated.

    Al
     
    alb, Mar 13, 2012
    #1
    1. Advertisements

  2. alb

    Tim Wescott Guest

    Does your linker take command files (e.g. foobar.ld)? If so, then you
    can put the thing into a segment of its own, and locate that segment
    where you want it. Or you can explicitly define the location in an
    assembly file (just define the symbol and make it global), then tell the
    linker that it's memory _really_ starts just above that variable.
     
    Tim Wescott, Mar 13, 2012
    #2
    1. Advertisements

  3. alb

    Rich Webb Guest

    Would a construct like this work?
    #define FIO0DIR (*(volatile unsigned long *)0x3FFFC000)

    It's often used to define registers that are in specific memory
    locations where you'd want to be able to, for example, make an
    assignment, like
    FIO0DIR = 0xDEADBEEF;

    However, you're probably best to modify the assembly-language run-time
    stub (e.g., crt.s or similar) and do as Tim suggests to define a
    specific section for the interrupt table.
     
    Rich Webb, Mar 13, 2012
    #3
  4. alb

    Tim Wescott Guest

    The problem with your method is that it doesn't prevent the linker from
    assigning some _other_ variable to that location, unless you tell the
    linker to stay away from that part of memory.

    Someone, either in a private mail or on this group, has mentioned that
    the tool set for that chip is a modified gcc chain. If that's so, then
    it uses ld, and ld uses linker files with a fairly well documented
    syntax, and part of that syntax is the ability to arbitrarily assign
    addresses to symbols and to arbitrarily locate segments.

    Here's a snippet from one of my linker scripts:

    SEARCH_DIR("/home/tim/arm-none-eabi/arm-none-eabi/thumb/lib");

    /* Symbols */

    GPIOA = 0x40004000;
    GPIOB = 0x40005000;

    /* etc. */

    NVIC = 0xE000E000;
    _stack = 0x20002000;

    MEMORY
    {
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K /* */
    /* FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K /* */
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
    }

    SECTIONS
    {
    .vectors :
    {
    } > FLASH

    .text :
    {
    KEEP(*(._vector_table))
    *(.vectors)
    *(.text* .text.* .gnu.linkonce.t.*)
    *(.plt)
    *(.gnu.warning)

    *(.rodata* .rodata.* .gnu.linkonce.r.*)

    /* etc. some more

    }

    In this case, the OP could either use a compiler directive to put
    ___lib_int_table into a special segment, then locate that segment at the
    start of data memory (similar to the way the .vectors segment is
    explicitly located before .text in the above linker command script), or
    the OP could put a statement in there like

    ___lib_int_table = <my desired address>;

    and start memory at the next word after ___lib_int_table. I'd do the
    special segment razz-matazz: it takes the size of ___lib_int_table into
    account, makes sure things are properly aligned, and even if it means
    depending on some non-portable features of the compiler, by the time you
    get that close to the hardware your C is getting pretty tool-dependent
    anyway.

    --
    My liberal friends think I'm a conservative kook.
    My conservative friends think I'm a liberal kook.
    Why am I not happy that they have found common ground?

    Tim Wescott, Communications, Control, Circuits & Software
    http://www.wescottdesign.com
     
    Tim Wescott, Mar 13, 2012
    #4
  5. alb

    Rich Webb Guest

    Indeed. And yes, this does look cleaner (and more reliable).
     
    Rich Webb, Mar 13, 2012
    #5
  6. alb

    alb Guest

    On 3/13/2012 5:08 PM, Tim Wescott wrote:
    [...]
    the tool set is a port from gcc but the linker (ld21k) doesn't seem to
    get anything as additional input except the 'architecture file' which it
    does not seem to me to allow the freedom your script is showing.
    It does not seem to me the architecture file syntax will allow this type
    of statements.
    The additional problem here is that ___lib_int_table is a global
    variable defined in the library as follows:

    !file int_tabl.asm
    #include "lib_glob.h"
    #include "sig_glob.h"

    ..SEGMENT/RAM_SPACE Ram_Space_Name;

    ..GLOBAL ___lib_int_table;
    ..VAR ___lib_int_table[___SIG_LAST_INTERRUPT * siga_size];

    ..ENDSEG

    Now the 'RAM_SPACE' is not understood by the linker at all, but when the
    library is compiled all the GLOBAL and VAR go in a segment called
    seg_dmda by default.

    When I link against this object I don't have a way to specify through
    the architecture file where it should go in the memory unless the object
    is first in the list of objects and then is automatically located at the
    beginning of the memory.

    On top of this, if I declare some static or global variable in my main.c
    file, then they will go first unless I first create the main.o and then
    call the linker separately to link the objects together.

    I can certainly avoid to declare static or global variables in my main.c
    (this is probably a good practice anyway), but was a headache before I
    realized what the hack the processor was doing.
     
    alb, Mar 14, 2012
    #6
  7. alb

    alb Guest

    On 3/14/2012 9:37 AM, alb wrote:
    [...]
    Ok RAM_SPACE is a #define for DM, while Ram_Space_Name is a define for
    seg_dmda. I think the author thought RAM_SPACE would have been more
    readable than DM... what a genius!
     
    alb, Mar 14, 2012
    #7
  8. alb

    Tim Wescott Guest

    I think you might be giving up too soon -- see if you can figure out how
    to give that vector it's own segment name, and diddle with your
    architecture file to see if you can put that segment where you want it.

    I would be _very_ surprised if there wasn't some way to achieve this.

    --
    My liberal friends think I'm a conservative kook.
    My conservative friends think I'm a liberal kook.
    Why am I not happy that they have found common ground?

    Tim Wescott, Communications, Control, Circuits & Software
    http://www.wescottdesign.com
     
    Tim Wescott, Mar 14, 2012
    #8
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.