-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathlink.x
More file actions
278 lines (228 loc) · 8.04 KB
/
link.x
File metadata and controls
278 lines (228 loc) · 8.04 KB
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
/*
Basic AArch32 linker script.
You must supply a file called `memory.x` in your linker search path. It must
define Region Aliases 'VECTORS', 'CODE', 'DATA', 'STACKS'.
Here is an example `memory.x` file:
-------------
MEMORY {
FLASH : ORIGIN = 0x08000000, LENGTH = 2M
SRAM : ORIGIN = 0x10000000, LENGTH = 512K
}
REGION_ALIAS("VECTORS", FLASH);
REGION_ALIAS("CODE", FLASH);
REGION_ALIAS("DATA", SRAM);
REGION_ALIAS("STACKS", SRAM);
-------------
The AArch32 platform uses seven separate stacks. The default sizes for each are
given at the bottom of this file. However, your `memory.x` can provide an
alternative size for any (or all) of them, provided that size is a multiple of
eight bytes. For example, your `memory.x` might include:
-------------
PROVIDE(_und_stack_size = 3456);
PROVIDE(_svc_stack_size = 3456);
PROVIDE(_abt_stack_size = 3456);
PROVIDE(_hyp_stack_size = 3456);
PROVIDE(_irq_stack_size = 3456);
PROVIDE(_fiq_stack_size = 3456);
PROVIDE(_sys_stack_size = 3456);
-------------
The stacks will be located at the top of the STACKS region by default. Use
`PROVIDE(_pack_stacks = 0)` to remove the padding and locate the stacks at the
bottom of that region instead.
Based upon the linker script from https://github.com/rust-embedded/cortex-m
*/
INCLUDE memory.x
ENTRY(_start);
EXTERN(_vector_table);
EXTERN(_start);
EXTERN(_default_handler);
SECTIONS {
/* # Vector Table
*
* Our ARM interrupt vector table, consisting of branch instructions to
* each exception handler.
*
* May include FIQ handler code at the end.
*/
.vector_table ORIGIN(VECTORS) : {
*(.vector_table)
} > VECTORS
/* # Text
*
* Our executable code.
*/
.text : {
__stext = .;
*(.text .text*)
__etext = .;
} > CODE
/* # Text
*
* Our constants.
*/
.rodata : {
__srodata = .;
*(.rodata .rodata*)
__erodata = .;
} > CODE
/* # Data
*
* Our global variables that are not initialised to zero.
*/
.data : ALIGN(4) {
. = ALIGN(4);
__sdata = .;
*(.data .data.*);
. = ALIGN(4);
/* NB: __edata defined lower down */
} > DATA AT>CODE
/*
* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to
* use the .data loading mechanism by pushing __edata. Note: do not change
* output region or load region in those user sections!
*/
. = ALIGN(4);
__edata = .;
/* LMA of .data */
__sidata = LOADADDR(.data);
/* # Block Starting Symbol (BSS)
*
* Our global variables that *are* initialised to zero.
*/
.bss (NOLOAD) : ALIGN(4) {
. = ALIGN(4);
__sbss = .;
*(.bss .bss* COMMON)
. = ALIGN(4);
/* NB: __ebss defined lower down */
} > DATA
/*
* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to
* use the .bss zeroing mechanism by pushing __ebss. Note: do not change
* output region or load region in those user sections!
*/
__ebss = .;
/* # Uninitialised Data
*
* Our global variables that have no defined initial value.
*/
.uninit (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__suninit = .;
*(.uninit .uninit.*);
. = ALIGN(4);
__euninit = .;
} > DATA
/* # Stack Padding
*
* A padding region to push the stacks to the top of the STACKS region.
* If `_pack_stacks == 0`, this is forced to be zero size, putting the
* stacks at the bottom of the STACK region.
*/
.filler (NOLOAD) : {
/* Move the .stacks section to the end of the STACKS memory region */
_next_region = ORIGIN(STACKS) + LENGTH(STACKS);
_start_moved_stacks = _next_region - SIZEOF(.stacks);
_start_stacks = _pack_stacks ? . : _start_moved_stacks;
FILL(0x00)
. = _start_stacks;
} > STACKS
/* # Stacks
*
* Space for all seven stacks.
*/
.stacks (NOLOAD) : ALIGN(8)
{
. = ALIGN(8);
/* Lowest address of allocated stack */
_stacks_low_end = .;
/* Stack for UND mode */
_und_stack_low_end = .;
. += (_und_stack_size * _num_cores);
_und_stack_high_end = .;
/* Stack for SVC mode */
_svc_stack_low_end = .;
. += (_svc_stack_size * _num_cores);
_svc_stack_high_end = .;
/* Stack for ABT mode */
_abt_stack_low_end = .;
. += (_abt_stack_size * _num_cores);
_abt_stack_high_end = .;
/* Stack for HYP mode */
_hyp_stack_low_end = .;
. += (_hyp_stack_size * _num_cores);
_hyp_stack_high_end = .;
/* Stack for IRQ mode */
_irq_stack_low_end = .;
. += (_irq_stack_size * _num_cores);
_irq_stack_high_end = .;
/* Stack for FIQ mode */
_fiq_stack_low_end = .;
. += (_fiq_stack_size * _num_cores);
_fiq_stack_high_end = .;
/* Stack for SYS mode */
_sys_stack_low_end = .;
. += (_sys_stack_size * _num_cores);
_sys_stack_high_end = .;
/* Highest address of allocated stack */
_stacks_high_end = .;
} > STACKS
/DISCARD/ : {
/* Discard any notes */
*(.note .note*)
/* Discard these unwinding/exception related symbols, they are not used */
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
/* Discard these exception related symbols, they are not used */
*(.ARM.extab* .gnu.linkonce.armextab.*)
}
}
/* We provide default sizes for the stacks for any not specified in memory.x (which was loaded first) */
PROVIDE(_und_stack_size = 16K);
PROVIDE(_svc_stack_size = 16K);
PROVIDE(_abt_stack_size = 16K);
PROVIDE(_hyp_stack_size = 16K);
PROVIDE(_irq_stack_size = 64);
PROVIDE(_fiq_stack_size = 64);
PROVIDE(_sys_stack_size = 16K);
/* Default to one CPU core (i.e. one copy of each stack) */
PROVIDE(_num_cores = 1);
/* Set this to 1 in memory.x to remove the filler section pushing the stacks to the end of STACKS. */
PROVIDE(_pack_stacks = 0);
/* Weak aliases for ASM default handlers */
PROVIDE(_start = _default_start);
PROVIDE(_asm_undefined_handler = _asm_default_undefined_handler);
PROVIDE(_asm_svc_handler = _asm_default_svc_handler);
PROVIDE(_asm_hvc_handler = _asm_default_hvc_handler);
PROVIDE(_asm_prefetch_abort_handler = _asm_default_prefetch_abort_handler);
PROVIDE(_asm_data_abort_handler = _asm_default_data_abort_handler);
/* TODO: Hyp handler goes here */
PROVIDE(_asm_irq_handler = _asm_default_irq_handler);
PROVIDE(_asm_fiq_handler = _asm_default_fiq_handler);
/* Weak aliases for C default handlers */
PROVIDE(_undefined_handler = _default_handler);
PROVIDE(_svc_handler = _default_handler);
PROVIDE(_hvc_handler = _default_handler);
PROVIDE(_prefetch_abort_handler = _default_handler);
PROVIDE(_data_abort_handler = _default_handler);
/* TODO: Hyp handler goes here */
PROVIDE(_irq_handler = _default_handler);
/* NB: There is no default C-language FIQ handler */
/* Check the stack sizes are all a multiple of eight bytes */
ASSERT(_und_stack_size % 8 == 0, "
ERROR(aarch32-rt): UND stack size (_und_stack_size) is not a multiple of 8 bytes");
ASSERT(_svc_stack_size % 8 == 0, "
ERROR(aarch32-rt): SVC stack size (_svc_stack_size) is not a multiple of 8 bytes");
ASSERT(_abt_stack_size % 8 == 0, "
ERROR(aarch32-rt): ABT stack size (_abt_stack_size) is not a multiple of 8 bytes");
ASSERT(_hyp_stack_size % 8 == 0, "
ERROR(aarch32-rt): HYP stack size (_hyp_stack_size) is not a multiple of 8 bytes");
ASSERT(_irq_stack_size % 8 == 0, "
ERROR(aarch32-rt): IRQ stack size (_irq_stack_size) is not a multiple of 8 bytes");
ASSERT(_fiq_stack_size % 8 == 0, "
ERROR(aarch32-rt): FIQ stack size (_fiq_stack_size) is not a multiple of 8 bytes");
ASSERT(_sys_stack_size % 8 == 0, "
ERROR(aarch32-rt): SYS stack size (_sys_stack_size) is not a multiple of 8 bytes");
ASSERT(_num_cores != 0, "
ERROR(aarch32-rt): Number of cores cannot be zero");
/* End of file */