EmbeddedRelated.com
Forums

specifying a memory location for global variable

Started by alb March 13, 2012
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

-- 
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
On Tue, 13 Mar 2012 16:04:17 +0100, alb wrote:

> 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.
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 Control system and signal processing consulting www.wescottdesign.com
On Tue, 13 Mar 2012 16:04:17 +0100, alb <alessandro.basili@cern.ch>
wrote:

>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.
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 Norfolk, VA
On Tue, 13 Mar 2012 11:34:31 -0400, Rich Webb wrote:

> On Tue, 13 Mar 2012 16:04:17 +0100, alb <alessandro.basili@cern.ch> > wrote: > >>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. > > 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.
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
On Tue, 13 Mar 2012 11:08:27 -0500, Tim Wescott <tim@seemywebsite.com>
wrote:

>On Tue, 13 Mar 2012 11:34:31 -0400, Rich Webb wrote: > >> On Tue, 13 Mar 2012 16:04:17 +0100, alb <alessandro.basili@cern.ch> >> wrote: >> >>>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. >> >> 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. > >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.
Indeed. And yes, this does look cleaner (and more reliable). -- Rich Webb Norfolk, VA
On 3/13/2012 5:08 PM, Tim Wescott wrote:
[...]
> > 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.
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.
> > Here's a snippet from one of my linker scripts: >
[...]
> > 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>;
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.
> > 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. >
On 3/14/2012 9:37 AM, alb wrote:
[...]
> !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. >
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!
On Wed, 14 Mar 2012 09:37:47 +0100, alb wrote:

> On 3/13/2012 5:08 PM, Tim Wescott wrote: [...] >> >> 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. > > 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. > > >> Here's a snippet from one of my linker scripts: >> > [...] >> >> 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>; > > 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. > > >> 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. >>
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