How to specify the location of an object in memory (GNU)

Started by Michel Kuenemann November 1, 2005
Dear LPC2000 Group,

I am using the KEIL IDE for ARM7 processors with the GNU Cygnus compiler on
a LPC2106 target. My
problem is that I cannot find in the documentation how to tell the compiler
to locate an object at a specified place (somwhere in flash memory, for
instance).

In another IDE I am using, I would write :

at 0x00016000 int base;

Can someone help me ?

Thank you.

Michel Kuenemann
KMS - France


An Engineer's Guide to the LPC2100 Series

Michel Kuenemann wrote:

>Dear LPC2000 Group,
>
>I am using the KEIL IDE for ARM7 processors with the GNU Cygnus compiler on
>a LPC2106 target. My
>problem is that I cannot find in the documentation how to tell the compiler
>to locate an object at a specified place (somwhere in flash memory, for
>instance). >
That would be the linker that would do the physical location of things.

Compilers build relocatable objects, linkers place those into regions
that you specify in the linker file (script).

TomW

>In another IDE I am using, I would write :
>
>at 0x00016000 int base;
>
>Can someone help me ?
>
>Thank you.
>
>Michel Kuenemann
>KMS - France >
>Yahoo! Groups Links


--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------


Tom Walsh wrote:

>Michel Kuenemann wrote: >
>>Dear LPC2000 Group,
>>
>>I am using the KEIL IDE for ARM7 processors with the GNU Cygnus compiler on
>>a LPC2106 target. My
>>problem is that I cannot find in the documentation how to tell the compiler
>>to locate an object at a specified place (somwhere in flash memory, for
>>instance).
>>
>>
>>
>>
>>
>That would be the linker that would do the physical location of things.
>
>Compilers build relocatable objects, linkers place those into regions
>that you specify in the linker file (script). >

Go here: http://www.openhardware.net

Then under "Documents Lib" select "Absolute Linking with gcc". In that
document, look at page 5 to see how things get hardcoded to an absolute
address. The document is rather old, I wrote it a number of years ago,
however, it is still pertinent to what we do today with the linker.

TomW --
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------




Hey Michel,

Michel wrote:
> I am using the KEIL IDE for ARM7 processors with the GNU Cygnus
> compiler on a LPC2106 target. My problem is that I cannot find
> in the documentation how to tell the compiler to locate an object
> at a specified place (somwhere in flash memory, for instance).
> at 0x00016000 int base;

TomW replied with:
> That would be the linker that would do the physical location of things.
>
> Compilers build relocatable objects, linkers place those into regions
> that you specify in the linker file (script).

Could you please tell us WHY you want to do this?

The only time I can ever think of needed to force a particular
code at a specific address is;

a) an exception vector(s)
b) an overlay for a set of device control registers

For (a) you can define a section, and use the linker script to
perform the locating in Flash. For (b), I've always found it
nicer to just use a pointer to the peripherals region instead,
eg.

typedef struct serial {
int control;
int status;
int data;
} serial_t;

serial_t *com1 = (serial_t *)(SERIAL_BASE_ADDR);

registers are accessed as com1->control = ...

If you use the linker to link this structure over a specific range
of addresses, then the syntax changes to com1.control = ...
But you have to do more work with the linker script.

So, perhaps you are trying to implement something the
difficult way, tell us what you are trying to do.

Cheers,
Dave



Hello Tom,

Thank you very much for your tip. I was searching in the wrong direction (as
usual).

Now I think I have found the way I should do this :

1 - In the linker script I declare a section ".iap" that begins at a given
address in the code space.

/* Beginning of the flash sector where I want to store data with IAP */

.iap 0x00016000 :
{
*(.iap)
} >CODE

. = ALIGN(4);

2 - In the C code I write something like :

long star __attribute__ ((section (".iap")));

I guess this will do the thing. I have checked in the map fil that the
address of "star" is 0x00016000.

Regards

Michel Kuenemann -----Message d'origine-----
De : lpc2000@lpc2... [mailto:lpc2000@lpc2...]De la part de
Tom Walsh
Envoy: mardi 1 novembre 2005 21:42
: lpc2000@lpc2...
Objet : Re: [lpc2000] How to specify the location of an object in memory
(GNU) Tom Walsh wrote:

>Michel Kuenemann wrote: >
>>Dear LPC2000 Group,
>>
>>I am using the KEIL IDE for ARM7 processors with the GNU Cygnus compiler
on
>>a LPC2106 target. My
>>problem is that I cannot find in the documentation how to tell the
compiler
>>to locate an object at a specified place (somwhere in flash memory, for
>>instance).
>>
>>
>>
>>
>>
>That would be the linker that would do the physical location of things.
>
>Compilers build relocatable objects, linkers place those into regions
>that you specify in the linker file (script). >

Go here: http://www.openhardware.net

Then under "Documents Lib" select "Absolute Linking with gcc". In that
document, look at page 5 to see how things get hardcoded to an absolute
address. The document is rather old, I wrote it a number of years ago,
however, it is still pertinent to what we do today with the linker.

TomW --
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------

SPONSORED LINKS Microprocessor Microcontrollers Pic microcontrollers
8051 microprocessor ----
--
YAHOO! GROUPS LINKS

a.. ----
--


Hi David,

You are completely right, I can give any adress the way you show it in your
example.

I can write

long *l = (long *) 0x00016000;

instead of declaring a section beginning at a given address in the linker
script.

Let's say it was a kind of exercise :-)

Regards

Michel Kuenemann -----Message d'origine-----
De : lpc2000@lpc2... [mailto:lpc2000@lpc2...]De la part de
David Hawkins
Envoy: mardi 1 novembre 2005 21:45
: lpc2000@lpc2...
Objet : RE: [lpc2000] How to specify the location of an object in
memory(GNU)

Hey Michel,

Michel wrote:
> I am using the KEIL IDE for ARM7 processors with the GNU Cygnus
> compiler on a LPC2106 target. My problem is that I cannot find
> in the documentation how to tell the compiler to locate an object
> at a specified place (somwhere in flash memory, for instance).
> at 0x00016000 int base;

TomW replied with:
> That would be the linker that would do the physical location of things.
>
> Compilers build relocatable objects, linkers place those into regions
> that you specify in the linker file (script).

Could you please tell us WHY you want to do this?

The only time I can ever think of needed to force a particular
code at a specific address is;

a) an exception vector(s)
b) an overlay for a set of device control registers

For (a) you can define a section, and use the linker script to
perform the locating in Flash. For (b), I've always found it
nicer to just use a pointer to the peripherals region instead,
eg.

typedef struct serial {
int control;
int status;
int data;
} serial_t;

serial_t *com1 = (serial_t *)(SERIAL_BASE_ADDR);

registers are accessed as com1->control = ...

If you use the linker to link this structure over a specific range
of addresses, then the syntax changes to com1.control = ...
But you have to do more work with the linker script.

So, perhaps you are trying to implement something the
difficult way, tell us what you are trying to do.

Cheers,
Dave ----
--
YAHOO! GROUPS LINKS

a.. ----
--


David Hawkins wrote:

>Hey Michel,
>
>Michel wrote: >>I am using the KEIL IDE for ARM7 processors with the GNU Cygnus
>>compiler on a LPC2106 target. My problem is that I cannot find
>>in the documentation how to tell the compiler to locate an object
>>at a specified place (somwhere in flash memory, for instance).
>>at 0x00016000 int base;
>>
>>
>
>TomW replied with: >>That would be the linker that would do the physical location of things.
>>
>>Compilers build relocatable objects, linkers place those into regions
>>that you specify in the linker file (script).
>>
>>
>
>Could you please tell us WHY you want to do this?
>
>The only time I can ever think of needed to force a particular
>code at a specific address is; >
Just because you know a couple of things doesn't mean that you know it all.

If you recognized the "AT" directive then you would have understood that
the question was regard to locating a section to a hard address.
Typically this is done to describe where something such as a binary
image produced by something other than the compiler. Or, it is done to
physically locate entire Sections of code into external memory devices.

Ok? > a) an exception vector(s)
> b) an overlay for a set of device control registers
>
>For (a) you can define a section, and use the linker script to
>perform the locating in Flash. For (b), I've always found it
>nicer to just use a pointer to the peripherals region instead,
>eg.
>
> typedef struct serial {
> int control;
> int status;
> int data;
> } serial_t;
>
> serial_t *com1 = (serial_t *)(SERIAL_BASE_ADDR);
>
> registers are accessed as com1->control = ...
>
>If you use the linker to link this structure over a specific range
>of addresses, then the syntax changes to com1.control = ...
>But you have to do more work with the linker script.
>
>So, perhaps you are trying to implement something the
>difficult way, tell us what you are trying to do.
>
>Cheers,
>Dave >
>
>Yahoo! Groups Links


--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------



Hey Tom,

> >The only time I can ever think of needed to force a
> >particular code at a specific address is;
> >
> Just because you know a couple of things doesn't mean that you
> know it all.
>

Sorry, wasn't trying to sound like I knew it all, on
the contrary, I'm learning too, so wanted to know why,
given that I knew of two possible options.

So, thanks for responding :)

> If you recognized the "AT" directive then you would have
> understood that the question was regard to locating a section
> to a hard address. Typically this is done to describe where
> something such as a binary image produced by something other
> than the compiler. Or, it is done to physically locate entire
> Sections of code into external memory devices.
>
> Ok?

Yep, I understand now that Michel responded with a more detailed
response and showed that he wanted to locate a function at a
specific address. His original email was vague on the 'why',
which was why I wrote my response.

Since you are familiar with linker scripts, perhaps you can answer
a question for me :)

In the LPC2138 manual (lpc213x_um.pdf p227) there are comments
regarding the assumed use of RAM by the on-chip functions;

RAM used by ISP command handler
ISP commands use on-chip RAM from 0x4000 0120 to 0x4000 01FF.
The user could use this area, but the contents may be lost
upon reset. Flash programming commands use the top 32 bytes of
on-chip RAM. The stack is located at RAM top - 32. The
maximum stack usage is 256 bytes and it grows downwards.

RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM.
The maximum stack usage in the user allocated stack space is
128 bytes and it grows downwards.

RAM used by RealMonitor
The RealMonitor uses on-chip RAM from 0x4000 0040 to 0x4000 011F.
The user could use this area if RealMonitor based debug is not
required. The Flash boot loader does not initialize the stack
for RealMonitor. If you wanted to enable each of these features, what would be your
recommeded way of dealing with the preassigned blocks of RAM;

a) define multiple memory sections

i.e., instead of the normal

MEMORY
{
flash (rx) : org = 0x00000000, len = 0x00080000
sram (rw) : org = 0x40000000, len = 0x00008000
}

write

MEMORY
{
flash (rx) : org = 0x00000000, len = 0x00080000

/* reserve for real monitor */
sram_rm (rw) : org = 0x40000040, len = 0x000000E0

/* reserve for IAP stack */
sram_isp (rw) : org = 0x40000120, len = 0x000000E0

/* User SRAM */
sram (rw) : org = 0x40000200, len = 0x00008000
}

(actually, I don't think the reserved memory sections even need
to be defined, unless you use them in the SECTIONS area, simply
moving the start of SRAM to 0x40000200 would seem appropriate).

or

b) Keep the first MEMORY sections above, and create dummy sections
in the SECTIONS area and eject them into the sram at the right
spot? Cheers,
Dave


David Hawkins wrote:

>Hey Tom, >
>>>The only time I can ever think of needed to force a
>>>particular code at a specific address is;
>>>
>>>
>>>
>>Just because you know a couple of things doesn't mean that you
>>know it all.
>>
>>
>>
>
>Sorry, wasn't trying to sound like I knew it all, on
>the contrary, I'm learning too, so wanted to know why,
>given that I knew of two possible options.
>
>So, thanks for responding :) >
It was my problem, not yours. Thank you anyway.

>>If you recognized the "AT" directive then you would have
>>understood that the question was regard to locating a section
>>to a hard address. Typically this is done to describe where
>>something such as a binary image produced by something other
>>than the compiler. Or, it is done to physically locate entire
>>Sections of code into external memory devices.
>>
>>Ok?
>>
>>
>
>Yep, I understand now that Michel responded with a more detailed
>response and showed that he wanted to locate a function at a
>specific address. His original email was vague on the 'why',
>which was why I wrote my response.
>
>Since you are familiar with linker scripts, perhaps you can answer
>a question for me :) >
The code examples that you mentioned before are appropriate for the
high-level referencing of objects, referencing where they lie in the
memory map. Linker scripts are for the physical placement of objects
within that memory map, the "ordering" of the memory.

IIRC, the "AT" was used by Microsoft in their linkers to describe where
fixed sections of memory resided. However, you could not fill that
region with code though, it was more of a template, a concept more than
physically usefull.

While most of the Philips LPC2xxx ARM chips have a simple memory
architecture, other ARM systems don't. With "classic" controller
systems, you have external RAM, ROM and hardware connected to chip
selects. The programmed value of the chip select regions along with the
linker script would be how you define where those objects resided and
gain access to them. Then you could use the typedef approach to further
refine that objects description and assign an address which points to
that object in C / Assembler.

By use of the linker, you can also describe a region of memory within
Flash / RAM as a kind of "hole", or protected area. As in "don't put
anything here". Then, using objcopy, you can pull out the individual
Sections (.text, .data, etc) from the linked image and put them into
seperate files. Then those seperate files can be physically combined
(cat'ed together) to build a ROM-able image.

We did this with the uClinux kernel, the kernel was ORG'ed to run at
0000h in RAM, and the file system was at the top of the RAM (end). In a
case such as that, you could have a huge distance between the RAM memory
address and that of the filesystem. The gap between the end of the
kernel and start of the filesystem was the Heap. This is what the
Absolute Linking with GCC doc described, how to deal with describing how
to logically place the two parts into the final image. As the final
image was ELF, not BINARY, the hole did not take up space, but we need
to get that ELF file into ROM / Compact Flash. This is where objcopy
came in.

For the LPC2000 series, creating such a "hole" is still an advantage.
The LPC2000 will execute code from RAM, you could describe an area of
the SRAM which is an area where you could pull executable code in from
an MMC / Compact Flash and execute it. For example, if you only need
your system configuration menus / user interactive setup code
infrequently, why put it in the valuable Flash area. You can simply
pull it in from the Flash Drive, execute it, and throw it away when you
are done!

Again, I apologize for my short temper. :-/ Regards,

TomW --
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------



Hey Tom,

> It was my problem, not yours. Thank you anyway.

No sweat, glad you are listening in on things and are
willing to share.

> We did this with the uClinux kernel ...

Yeah, I took a look at your the reference you posted on
http://openhardware.net.

Thanks again,
Dave