lpc: Stick magic value at 0x2fc to let us use PIO0_1
[fw/altos] / src / lpc / altos-loader.ld
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 __flash = 0x300;
20 __flash_size = 4K - 0x300;
21 __ram = 0x10000000;
22 __ram_size = 4k;
23 __stack_size = 128;
24
25 INCLUDE registers.ld
26 /*
27  * SPDX-License-Identifier: BSD-3-Clause
28  *
29  * Copyright © 2019 Keith Packard
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  *
38  * 2. Redistributions in binary form must reproduce the above
39  *    copyright notice, this list of conditions and the following
40  *    disclaimer in the documentation and/or other materials provided
41  *    with the distribution.
42  *
43  * 3. Neither the name of the copyright holder nor the names of its
44  *    contributors may be used to endorse or promote products derived
45  *    from this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
50  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
51  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
52  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58  * OF THE POSSIBILITY OF SUCH DAMAGE.
59  */
60
61 ENTRY(_start)
62
63 /*
64  * These values should be provided by the application. We'll include
65  * some phony values here to make things link for testing
66  */
67
68 MEMORY
69 {
70         low (rxai!w)   : ORIGIN = 0x0, LENGTH = 0x2fc
71         no_isp (rxai!w): ORIGIN = 0x2fc, LENGTH = 4
72         flash (rxai!w) : ORIGIN = DEFINED(__flash) ? __flash : 0x10000000, LENGTH = DEFINED(__flash_size) ? __flash_size : 0x10000
73         ram (wxa!ri)   : ORIGIN = DEFINED(__ram  ) ? __ram   : 0x20000000, LENGTH = DEFINED(__ram_size  ) ? __ram_size   : 0x08000
74 }
75
76 PHDRS
77 {
78         text PT_LOAD;
79         ram PT_LOAD;
80         ram_init PT_LOAD;
81         tls PT_TLS;
82 }
83
84 SECTIONS
85 {
86         PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram));
87
88         .no_isp : {
89                 *(.no_isp)
90         } > no_isp AT>no_isp :text
91
92         .init : {
93                 KEEP (*(.text.init.enter))
94                 KEEP (*(.data.init.enter))
95                 KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*)))
96         } >low AT>low :text
97
98         .text.low : {
99                 ao_boot_chain.o(.text .text.*)
100                 ao_boot_pin.o(.text .text.*)
101                 ao_product.o(.rodata .rodata.*)
102         } >low AT>low :text
103
104         .text : {
105
106                 /* code */
107                 *(.text.unlikely .text.unlikely.*)
108                 *(.text.startup .text.startup.*)
109                 *(.text .text.*)
110                 *(.gnu.linkonce.t.*)
111                 KEEP (*(.fini .fini.*))
112                 __text_end = .;
113
114                 PROVIDE (__etext = __text_end);
115                 PROVIDE (_etext = __text_end);
116                 PROVIDE (etext = __text_end);
117
118                 /* read-only data */
119                 *(.rdata)
120                 *(.rodata .rodata.*)
121                 *(.gnu.linkonce.r.*)
122
123                 *(.srodata.cst16)
124                 *(.srodata.cst8)
125                 *(.srodata.cst4)
126                 *(.srodata.cst2)
127                 *(.srodata .srodata.*)
128                 *(.data.rel.ro .data.rel.ro.*)
129                 *(.got .got.*)
130
131                 /* Need to pre-align so that the symbols come after padding */
132                 . = ALIGN(8);
133
134                 /* lists of constructors and destructors */
135                 PROVIDE_HIDDEN ( __preinit_array_start = . );
136                 KEEP (*(.preinit_array))
137                 PROVIDE_HIDDEN ( __preinit_array_end = . );
138
139                 PROVIDE_HIDDEN ( __init_array_start = . );
140                 KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
141                 KEEP (*(.init_array .ctors))
142                 PROVIDE_HIDDEN ( __init_array_end = . );
143
144                 PROVIDE_HIDDEN ( __fini_array_start = . );
145                 KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
146                 KEEP (*(.fini_array .dtors))
147                 PROVIDE_HIDDEN ( __fini_array_end = . );
148         } >flash AT>flash :text
149
150         /* additional sections when compiling with C++ exception support */
151         /*
152         .except_ordered : {
153                 *(.gcc_except_table *.gcc_except_table.*)
154                 KEEP (*(.eh_frame .eh_frame.*))
155                 *(.ARM.extab* .gnu.linkonce.armextab.*)
156         } >flash AT>flash :text
157
158         .except_unordered : {
159                 . = ALIGN(8);
160
161                 PROVIDE(__exidx_start = .);
162                 *(.ARM.exidx*)
163                 PROVIDE(__exidx_end = .);
164         } >flash AT>flash :text
165         */
166
167         /*
168          * Data values which are preserved across reset
169          */
170         .preserve (NOLOAD) : {
171                 PROVIDE(__preserve_start__ = .);
172                 KEEP(*(SORT_BY_NAME(.preserve.*)))
173                 KEEP(*(.preserve))
174                 PROVIDE(__preserve_end__ = .);
175         } >ram AT>ram :ram
176
177         .data : ALIGN_WITH_INPUT {
178                 *(.data .data.*)
179                 *(.gnu.linkonce.d.*)
180
181                 /* Need to pre-align so that the symbols come after padding */
182                 . = ALIGN(8);
183
184                 PROVIDE( __global_pointer$ = . + 0x800 );
185                 *(.sdata .sdata.* .sdata2.*)
186                 *(.gnu.linkonce.s.*)
187         } >ram AT>flash :ram_init
188         PROVIDE(__data_start = ADDR(.data));
189         PROVIDE(__data_source = LOADADDR(.data));
190
191         /* Thread local initialized data. This gets
192          * space allocated as it is expected to be placed
193          * in ram to be used as a template for TLS data blocks
194          * allocated at runtime. We're slightly abusing that
195          * by placing the data in flash where it will be copied
196          * into the allocate ram addresses by the existing
197          * data initialization code in crt0
198          */
199         .tdata : ALIGN_WITH_INPUT {
200                 *(.tdata .tdata.* .gnu.linkonce.td.*)
201                 PROVIDE(__data_end = .);
202                 PROVIDE(__tdata_end = .);
203         } >ram AT>flash :tls :ram_init
204         PROVIDE( __tls_base = ADDR(.tdata));
205         PROVIDE( __tdata_start = ADDR(.tdata));
206         PROVIDE( __tdata_source = LOADADDR(.tdata) );
207         PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) );
208         PROVIDE( __tdata_size = SIZEOF(.tdata) );
209
210         PROVIDE( __edata = __data_end );
211         PROVIDE( _edata = __data_end );
212         PROVIDE( edata = __data_end );
213         PROVIDE( __data_size = __data_end - __data_start );
214
215         .tbss (NOLOAD) : {
216                 *(.tbss .tbss.* .gnu.linkonce.tb.*)
217                 *(.tcommon)
218                 PROVIDE( __tls_end = . );
219                 PROVIDE( __tbss_end = . );
220         } >ram AT>ram :tls :ram
221         PROVIDE( __bss_start = ADDR(.tbss));
222         PROVIDE( __tbss_start = ADDR(.tbss));
223         PROVIDE( __tbss_size = SIZEOF(.tbss) );
224         PROVIDE( __tls_size = __tls_end - __tls_base );
225
226         /*
227          * The linker special cases .tbss segments which are
228          * identified as segments which are not loaded and are
229          * thread_local.
230          *
231          * For these segments, the linker does not advance 'dot'
232          * across them.  We actually need memory allocated for tbss,
233          * so we create a special segment here just to make room
234          */
235         .tbss_space (NOLOAD) : {
236                 . = . + SIZEOF(.tbss);
237         } >ram AT>ram :ram
238
239         .bss (NOLOAD) : {
240                 *(.sbss*)
241                 *(.gnu.linkonce.sb.*)
242                 *(.bss .bss.*)
243                 *(.gnu.linkonce.b.*)
244                 *(COMMON)
245
246                 /* Align the heap */
247                 . = ALIGN(8);
248                 __bss_end = .;
249         } >ram AT>ram :ram
250         PROVIDE( __end = __bss_end );
251         PROVIDE( _end = __bss_end );
252         PROVIDE( end = __bss_end );
253         PROVIDE( __bss_size = __bss_end - __bss_start );
254
255         /* Make the rest of memory available for heap storage */
256         PROVIDE (__heap_start = __end);
257         PROVIDE (__heap_end = __stack - (DEFINED(__stack_size) ? __stack_size : 0x800));
258         PROVIDE (__heap_size = __heap_end - __heap_start);
259
260         /* Define a stack region to make sure it fits in memory */
261         .stack (NOLOAD) : {
262                 . += (DEFINED(__stack_size) ? __stack_size : 0x800);
263         } >ram :ram
264
265         /* Throw away C++ exception handling information */
266
267         
268
269         /DISCARD/ : {
270                 *(.note .note.*)
271                 *(.eh_frame .eh_frame.*)
272                 *(.ARM.extab* .gnu.linkonce.armextab.*)
273                 *(.ARM.exidx*)
274         }
275
276         
277 }