summaryrefslogtreecommitdiffstats
path: root/doc/bsp_howto/linkcmds.t
blob: b221dceaa8349a4f6f5f48d3cb417fec194eaccb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
@chapter = Linkcmds

@subsection = What is a "linkcmds" file?

The linkcmds file is a script which is passed to the linker at linking
time. It holds somewhat the board memory configuration. 

@subsection = Image of an Executable

A program destined to be embedded has some specificities. Embedded
machines often mean average performances and small memory usage. 

Two types of memories have to be distinguished: one is volatile but on
read and write access (RAM), while the other is non-volatile but read only
(ROM). Even though RAM and ROM can be found in every personal computer,
one generally doesn't care about them , because a program is always put in
RAM and is executed in RAM. That's a bit different in embedded
development: the target will execute the program each time it's reboot or
switched on, which means the program is stored in ROM. On the other hand,
data pr ocessing occurs in RAM. 



That leads us to the structure of an embedded program: it's roughly made
of sections, for instance for the Motorola 68k family of microprocessors : 

@itemize @bullet

@item the code section (aka ".txt" section): it holds the program's main
code, so that it doesn't have to be modified. It's placed in ROM. 

@item the non-initialized data section (aka ".bss" section): it holds non
initialized variables of the program. It can stay in RAM. 

@item the initialized data section (aka ".data" section): it holds the
program data which are to be modified during the program's life, which
means they have to be in RAM. On another hand, these variables must be set
to predefined values, which have to be
 stored in ROM... 

@end itemize

That brings us up to the notion of the image of an executable: it consists
in the set of the program sections. 



As a program executable has many sections (note that the user can define
his own, and that compilers define theirs without any notice), one has to
state in which type of memory (RAM or ROM) the sections will be arranged.
For instance, a program compiled f or a Personal Computer will see all the
sections to go to RAM, while a program destined to be embedded will see
some of his sections going into the ROM. 



The (section, area of memory) connection is made at linking time. One have
to make the linker know the different sections location once they're in
memory. 


Figure 2 : sections location in memory 

The GNU linker has a command language to specify the image format.  Let's
have a look to the "gen68340"  BSP linkcmds, which can be found at
$BSP340_ROOT/startup/linkcmds. 


@example
OUTPUT_FORMAT(coff-m68k) 

RamSize = DEFINED(RamSize) ? RamSize : 4M;
HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
StackSize = DEFINED(StackSize) ? StackSize : 0x1000;

MEMORY {
          ram : ORIGIN = 0x10000000, LENGTH = 4M
          rom : ORIGIN = 0x01000000, LENGTH = 4M
}

ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;

/*
 * Load objects
 */
SECTIONS {
	/*
	 * Hardware variations
	 */
	_RamSize = RamSize;
	__RamSize = RamSize;

        /*
         * Boot PROM
         */
        rom : {
                _RomBase = .;
                __RomBase = .;
        } >rom

        /*
         * Dynamic RAM
         */
        ram : {
                _RamBase = .;
                __RamBase = .;
        } >ram

        /*
         * Text, data and bss segments
         */
        .text : {
                CREATE_OBJECT_SYMBOLS


                *(.text)


                . = ALIGN (16);


		/*
		 * C++ constructors
		 */
		__CTOR_LIST__ = .;
               [......]
		__DTOR_END__ = .;

                etext = .;
                _etext = .;
        } >rom 

	.eh_fram : {
		. = ALIGN (16);
		*(.eh_fram)
	} >ram

	.gcc_exc : {
		. = ALIGN (16);
		*(.gcc_exc)
	} >ram

        dpram : {
                m340 = .;
                _m340 = .;
                . += (8 * 1024);
        } >ram

        .data : {
                copy_start = .;
                *(.data)

                . = ALIGN (16);
                _edata = .;
                copy_end = .;
        } >ram

        .bss : {
                M68Kvec = .;
                _M68Kvec = .;
                . += (256 * 4);


                clear_start = .;

                *(.bss)

                *(COMMON)

                . = ALIGN (16);
                _end = .;

                _HeapStart = .;
                __HeapStart = .;
                . += HeapSize;  
                . += StackSize;
                . = ALIGN (16);
                stack_init = .;

                clear_end = .;

                _WorkspaceBase = .;
                __WorkspaceBase = .;



        } >ram
}
@end example

executable format is COFF

your default board RAM size here. 

Note that it's possible to change it by passing an argument to ld

the default heap size: beware! the heap must be large enough to contain: 

@itemize @bullet

@item your program's static allocations

@item your program's dynamic allocations

@item ALL YOUR PROCESS'S STACK

@end itemize

Having a tight heap size is somewhat difficult and many tries are needed
if you want to save the memory usage. 


The Stacksize should only be large enough to hold the stack in the
initialization sequence. Then the tasks stacks will be allocated in the
Heap. 

Start address of RAM and its length. 

The start address must be a valid address. Most often RAM is assigned to a
given chip of memory on the board, and a Chip Select is assigned to this
chip with an address (see the Initialization sequence chapter).


Start address of ROM and its length.  Same remarks as above. 

this is for the network driver (see KA9Q documentation for more details) 

define where the sections should go: 

define some variables that the user code can access.

set the RomBase variable to the start of the ROM.

set the RamBase variable to the start of the RAM.

states that a symbol shall be created for each object (.o)

insert the .text sections of every object

go to a frontier of 16 bytes (just keep it as is)

reserve some place for C++ constructors and destructors.

just keep it as is (or see CROSSGCC mailing-list FAQ for more details)

declares where the .txt section ends.

the .txt section goes in ROM!

this section is created by GCC

put it in RAM.

this section is created by GCC

put it in RAM

room for peripherals

needs 8 Kbytes
put it in RAM

the initialized data section

put all the objects' .data sections in the .data section of the image

.data section goes in RAM

the non initialized data section


reserve some room for the Table of Vector Interrupts (256 vectors of 4 bytes)

pointer to the start of the non initialized data

put all the objects .bss sections in the .bss section of the image

put all the non initialized data, which are not in .bss sections

Heap start

reserve some room for the heap

reserve some room for the stack

top of the stack (remember the stack grows with addresses going down)

end of the non initialized data

start of the RTEMS Workspace (holds RTEMS configuration table and a few
other things, its size is calculated by RTEMS according to your
configuration, <INSERT A LINK HERE>) 

the resulting .bss section goes in RAM


Now there's a problem with the initialized data: the .data section has to
be in RAM as these data are to be modified during the program execution.
But how will they be initialized at boot time? 



One should be aware of the running executable image and the file to
download to the target image being different! In practice, the initialized
data section is copied at the end of the code section (i.e. in ROM) when
building a PROM image. The GNU tool obj copy can be used for this purpose. 



Figure 3 : copy of the initialized data section to build a PROM image



This process is made after the linking time, and you can find an example
of how it is done in $RTEMS_ROOT/make/custom/gen68340.cfg : 

@example
# make a prom image
m68k-rtems-objcopy \
--adjust-section-vma .data= \

`m68k-rtems-objdump --section-headers \
$(basename $@).exe \
| awk '[...]` \
$(basename $@).exe
@end example

use the target objcopy

we want to move the start of the section .data

in the resulting image

the address is given by extracting the address of the end of the .text
section (i.e. in ROM) with an awk script (don't care about it) 

process the image which have just been linked



The board initialization code (cf. 6) will copy the initialized data
initial values (which are stored in ROM) to their reserved location in
RAM.