Browse Source

Add ability to build combined images

Brian Starkey 2 years ago
parent
commit
8fd36b7096
7 changed files with 1225 additions and 2 deletions
  1. 97
    2
      CMakeLists.txt
  2. 258
    0
      bootloader.ld
  3. 276
    0
      bootloader_shell.ld
  4. 248
    0
      combined.ld
  5. 59
    0
      gen_imghdr.py
  6. 53
    0
      mkasm.py
  7. 234
    0
      standalone.ld

+ 97
- 2
CMakeLists.txt View File

@@ -1,10 +1,36 @@
1
+# Derived from the Pico SDK, which carries the following
2
+# LICENSE.txt:
3
+# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
4
+#
5
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6
+# following conditions are met:
7
+#
8
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
9
+#    disclaimer.
10
+#
11
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12
+#    disclaimer in the documentation and/or other materials provided with the distribution.
13
+#
14
+# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
15
+#    derived from this software without specific prior written permission.
16
+#
17
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
+
1 25
 cmake_minimum_required(VERSION 3.13)
2 26
 
3 27
 include(pico_sdk_import.cmake)
4 28
 
5 29
 project(picowota C CXX ASM)
30
+
6 31
 set(CMAKE_C_STANDARD 11)
7 32
 set(CMAKE_CXX_STANDARD 17)
33
+
8 34
 pico_sdk_init()
9 35
 
10 36
 add_executable(picowota
@@ -13,13 +39,24 @@ add_executable(picowota
13 39
 	tcp_comm.c
14 40
 )
15 41
 
16
-pico_enable_stdio_usb(picowota 1)
42
+function(target_cl_options option)
43
+    target_compile_options(picowota PRIVATE ${option})
44
+    target_link_options(picowota PRIVATE ${option})
45
+endfunction()
46
+
47
+target_cl_options("-Wall")
48
+target_cl_options("-Os")
49
+target_cl_options("-ffunction-sections")
50
+target_cl_options("-fdata-sections")
51
+target_link_options(picowota PRIVATE "LINKER:--gc-sections")
17 52
 
18 53
 pico_add_extra_outputs(picowota)
19
-set_target_properties(picowota PROPERTIES COMPILE_FLAGS "-Wall -Os")
20 54
 
55
+# Needed so that lwip can find lwipopts.h
21 56
 target_include_directories(picowota PRIVATE ${CMAKE_CURRENT_LIST_DIR})
22 57
 
58
+pico_enable_stdio_usb(picowota 1)
59
+
23 60
 add_subdirectory(picowota_reboot)
24 61
 
25 62
 target_link_libraries(picowota
@@ -34,3 +71,61 @@ target_link_libraries(picowota
34 71
 	pico_util
35 72
 	picowota_reboot
36 73
 )
74
+
75
+# Provide a helper to build a standalone target
76
+function(picowota_build_standalone NAME)
77
+	get_target_property(PICOWOTA_SRC_DIR picowota SOURCE_DIR)
78
+	pico_set_linker_script(${NAME} ${PICOWOTA_SRC_DIR}/standalone.ld)
79
+	pico_add_bin_output(${NAME})
80
+endfunction()
81
+
82
+# Provide a helper to build a combined target
83
+# The build process is roughly:
84
+# 1. Build the bootloader, using a special linker script which leaves
85
+#    two sections to be filled in with the header (.app_hdr) and
86
+#    app binary (.app_bin)
87
+# 2. Build the app binary, using a special linker script to set the load
88
+#    address properly and skip boot2.
89
+# 3. Calculate the checksum of the app binary
90
+# 4. Update the header and binary sections in the ELF from 1.
91
+function(picowota_build_combined NAME)
92
+	set(APP_BIN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin)
93
+	set(APP_HDR_BIN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_hdr.bin)
94
+	set(COMBINED picowota_${NAME})
95
+	get_target_property(PICOWOTA_SRC_DIR picowota SOURCE_DIR)
96
+	get_target_property(PICOWOTA_BIN_DIR picowota BINARY_DIR)
97
+
98
+	# The app must be built with the correct linker script (and a .bin)
99
+	picowota_build_standalone(${NAME})
100
+
101
+	# Build the bootloader with the sections to fill in
102
+	pico_set_linker_script(picowota ${PICOWOTA_SRC_DIR}/bootloader_shell.ld)
103
+
104
+	# TODO: The hard-coded address here is a bit nasty
105
+	add_custom_target(${NAME}_hdr DEPENDS ${APP_BIN})
106
+	add_custom_command(TARGET ${NAME}_hdr DEPENDS ${APP_BIN}
107
+		COMMAND ${PICOWOTA_SRC_DIR}/gen_imghdr.py -a 0x1005B000 ${APP_BIN} ${APP_HDR_BIN}
108
+	)
109
+
110
+	add_custom_target(${COMBINED} ALL)
111
+	add_dependencies(${COMBINED} picowota ${NAME}_hdr ${NAME})
112
+	add_custom_command(TARGET ${COMBINED} DEPENDS ${APP_HDR_BIN} ${APP_BIN}
113
+		COMMAND ${CMAKE_OBJCOPY}
114
+			--update-section .app_hdr=${APP_HDR_BIN}
115
+			--update-section .app_bin=${APP_BIN} ${PICOWOTA_BIN_DIR}/picowota.elf ${COMBINED}.elf
116
+	)
117
+
118
+	add_custom_command(TARGET ${COMBINED} POST_BUILD
119
+		COMMAND ${CMAKE_OBJCOPY} -Obinary ${COMBINED}.elf ${COMBINED}.bin
120
+	)
121
+
122
+	if (NOT ELF2UF2_FOUND)
123
+		set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PICO_SDK_PATH}/tools)
124
+		find_package(ELF2UF2)
125
+	endif()
126
+	if (ELF2UF2_FOUND)
127
+		add_custom_command(TARGET ${COMBINED} POST_BUILD
128
+			COMMAND ELF2UF2 ${COMBINED}.elf ${COMBINED}.uf2
129
+	)
130
+	endif()
131
+endfunction()

+ 258
- 0
bootloader.ld View File

@@ -0,0 +1,258 @@
1
+/* Based on GCC ARM embedded samples.
2
+   Defines the following symbols for use by code:
3
+    __exidx_start
4
+    __exidx_end
5
+    __etext
6
+    __data_start__
7
+    __preinit_array_start
8
+    __preinit_array_end
9
+    __init_array_start
10
+    __init_array_end
11
+    __fini_array_start
12
+    __fini_array_end
13
+    __data_end__
14
+    __bss_start__
15
+    __bss_end__
16
+    __end__
17
+    end
18
+    __HeapLimit
19
+    __StackLimit
20
+    __StackTop
21
+    __stack (== StackTop)
22
+*/
23
+
24
+/*
25
+ * TODO: Hard-code 360k, which is the size I see on my machine with
26
+ * 'sta' mode and debug printf.
27
+ * There must be a better way to determine the size dynamically somehow.
28
+ */
29
+MEMORY
30
+{
31
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 360k
32
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
33
+    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
34
+    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
35
+}
36
+
37
+ENTRY(_entry_point)
38
+
39
+SECTIONS
40
+{
41
+    /* Second stage bootloader is prepended to the image. It must be 256 bytes big
42
+       and checksummed. It is usually built by the boot_stage2 target
43
+       in the Raspberry Pi Pico SDK
44
+    */
45
+
46
+    .flash_begin : {
47
+        __flash_binary_start = .;
48
+    } > FLASH
49
+
50
+    .boot2 : {
51
+        __boot2_start__ = .;
52
+        KEEP (*(.boot2))
53
+        __boot2_end__ = .;
54
+    } > FLASH
55
+
56
+    ASSERT(__boot2_end__ - __boot2_start__ == 256,
57
+        "ERROR: Pico second stage bootloader must be 256 bytes in size")
58
+
59
+    /* The second stage will always enter the image at the start of .text.
60
+       The debugger will use the ELF entry point, which is the _entry_point
61
+       symbol if present, otherwise defaults to start of .text.
62
+       This can be used to transfer control back to the bootrom on debugger
63
+       launches only, to perform proper flash setup.
64
+    */
65
+
66
+    .flashtext : {
67
+        __logical_binary_start = .;
68
+        KEEP (*(.vectors))
69
+        KEEP (*(.binary_info_header))
70
+        __binary_info_header_end = .;
71
+        KEEP (*(.reset))
72
+    }
73
+
74
+    .rodata : {
75
+        /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
76
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
77
+        . = ALIGN(4);
78
+    } > FLASH
79
+
80
+    .ARM.extab :
81
+    {
82
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
83
+    } > FLASH
84
+
85
+    __exidx_start = .;
86
+    .ARM.exidx :
87
+    {
88
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
89
+    } > FLASH
90
+    __exidx_end = .;
91
+
92
+    /* Machine inspectable binary information */
93
+    . = ALIGN(4);
94
+    __binary_info_start = .;
95
+    .binary_info :
96
+    {
97
+        KEEP(*(.binary_info.keep.*))
98
+        *(.binary_info.*)
99
+    } > FLASH
100
+    __binary_info_end = .;
101
+    . = ALIGN(4);
102
+
103
+    /* Vector table goes first in RAM, to avoid large alignment hole */
104
+   .ram_vector_table (COPY): {
105
+        *(.ram_vector_table)
106
+    } > RAM
107
+
108
+    .text : {
109
+        __ram_text_start__ = .;
110
+        *(.init)
111
+        *(.text*)
112
+        *(.fini)
113
+        /* Pull all c'tors into .text */
114
+        *crtbegin.o(.ctors)
115
+        *crtbegin?.o(.ctors)
116
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
117
+        *(SORT(.ctors.*))
118
+        *(.ctors)
119
+        /* Followed by destructors */
120
+        *crtbegin.o(.dtors)
121
+        *crtbegin?.o(.dtors)
122
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
123
+        *(SORT(.dtors.*))
124
+        *(.dtors)
125
+
126
+        *(.eh_frame*)
127
+        . = ALIGN(4);
128
+        __ram_text_end__ = .;
129
+    } > RAM AT> FLASH
130
+    __ram_text_source__ = LOADADDR(.text);
131
+
132
+
133
+    .data : {
134
+        __data_start__ = .;
135
+        *(vtable)
136
+
137
+        *(.time_critical*)
138
+
139
+        . = ALIGN(4);
140
+        *(.rodata*)
141
+        . = ALIGN(4);
142
+
143
+        *(.data*)
144
+
145
+        . = ALIGN(4);
146
+        *(.after_data.*)
147
+        . = ALIGN(4);
148
+        /* preinit data */
149
+        PROVIDE_HIDDEN (__mutex_array_start = .);
150
+        KEEP(*(SORT(.mutex_array.*)))
151
+        KEEP(*(.mutex_array))
152
+        PROVIDE_HIDDEN (__mutex_array_end = .);
153
+
154
+        . = ALIGN(4);
155
+        /* preinit data */
156
+        PROVIDE_HIDDEN (__preinit_array_start = .);
157
+        KEEP(*(SORT(.preinit_array.*)))
158
+        KEEP(*(.preinit_array))
159
+        PROVIDE_HIDDEN (__preinit_array_end = .);
160
+
161
+        . = ALIGN(4);
162
+        /* init data */
163
+        PROVIDE_HIDDEN (__init_array_start = .);
164
+        KEEP(*(SORT(.init_array.*)))
165
+        KEEP(*(.init_array))
166
+        PROVIDE_HIDDEN (__init_array_end = .);
167
+
168
+        . = ALIGN(4);
169
+        /* finit data */
170
+        PROVIDE_HIDDEN (__fini_array_start = .);
171
+        *(SORT(.fini_array.*))
172
+        *(.fini_array)
173
+        PROVIDE_HIDDEN (__fini_array_end = .);
174
+
175
+        *(.jcr)
176
+        . = ALIGN(4);
177
+        /* All data end */
178
+        __data_end__ = .;
179
+    } > RAM AT> FLASH
180
+    /* __etext is the name of the .data init source pointer (...) */
181
+    __etext = LOADADDR(.data);
182
+
183
+    .uninitialized_data (COPY): {
184
+        . = ALIGN(4);
185
+        *(.uninitialized_data*)
186
+    } > RAM
187
+
188
+    /* Start and end symbols must be word-aligned */
189
+    .scratch_x : {
190
+        __scratch_x_start__ = .;
191
+        *(.scratch_x.*)
192
+        . = ALIGN(4);
193
+        __scratch_x_end__ = .;
194
+    } > SCRATCH_X AT > FLASH
195
+    __scratch_x_source__ = LOADADDR(.scratch_x);
196
+
197
+    .scratch_y : {
198
+        __scratch_y_start__ = .;
199
+        *(.scratch_y.*)
200
+        . = ALIGN(4);
201
+        __scratch_y_end__ = .;
202
+    } > SCRATCH_Y AT > FLASH
203
+    __scratch_y_source__ = LOADADDR(.scratch_y);
204
+
205
+    .bss  : {
206
+        . = ALIGN(4);
207
+        __bss_start__ = .;
208
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
209
+        *(COMMON)
210
+        . = ALIGN(4);
211
+        __bss_end__ = .;
212
+    } > RAM
213
+
214
+    .heap (COPY):
215
+    {
216
+        __end__ = .;
217
+        end = __end__;
218
+        *(.heap*)
219
+        __HeapLimit = .;
220
+    } > RAM
221
+
222
+    /* .stack*_dummy section doesn't contains any symbols. It is only
223
+     * used for linker to calculate size of stack sections, and assign
224
+     * values to stack symbols later
225
+     *
226
+     * stack1 section may be empty/missing if platform_launch_core1 is not used */
227
+
228
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
229
+     * stack is not used then all of SCRATCH_X is free.
230
+     */
231
+    .stack1_dummy (COPY):
232
+    {
233
+        *(.stack1*)
234
+    } > SCRATCH_X
235
+    .stack_dummy (COPY):
236
+    {
237
+        *(.stack*)
238
+    } > SCRATCH_Y
239
+
240
+    .flash_end : {
241
+        __flash_binary_end = .;
242
+    } > FLASH
243
+
244
+    /* stack limit is poorly named, but historically is maximum heap ptr */
245
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
246
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
247
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
248
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
249
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
250
+    PROVIDE(__stack = __StackTop);
251
+
252
+    /* Check if data + heap + stack exceeds RAM limit */
253
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
254
+
255
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
256
+    /* todo assert on extra code */
257
+}
258
+

+ 276
- 0
bootloader_shell.ld View File

@@ -0,0 +1,276 @@
1
+/* Based on GCC ARM embedded samples.
2
+   Defines the following symbols for use by code:
3
+    __exidx_start
4
+    __exidx_end
5
+    __etext
6
+    __data_start__
7
+    __preinit_array_start
8
+    __preinit_array_end
9
+    __init_array_start
10
+    __init_array_end
11
+    __fini_array_start
12
+    __fini_array_end
13
+    __data_end__
14
+    __bss_start__
15
+    __bss_end__
16
+    __end__
17
+    end
18
+    __HeapLimit
19
+    __StackLimit
20
+    __StackTop
21
+    __stack (== StackTop)
22
+*/
23
+
24
+/*
25
+ * TODO: Hard-code 360k, which is the max size I see on my machine with
26
+ * 'sta' mode and debug printf.
27
+ * There must be a better way to determine the size dynamically somehow.
28
+ */
29
+MEMORY
30
+{
31
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 360k
32
+    FLASH_IMGHDR(rx) : ORIGIN = 0x10000000 + 360k, LENGTH = 4k
33
+    FLASH_APP(rx) : ORIGIN = 0x10000000 + 364k, LENGTH = 2048k - 364k
34
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
35
+    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
36
+    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
37
+}
38
+
39
+ENTRY(_entry_point)
40
+
41
+SECTIONS
42
+{
43
+    /* Second stage bootloader is prepended to the image. It must be 256 bytes big
44
+       and checksummed. It is usually built by the boot_stage2 target
45
+       in the Raspberry Pi Pico SDK
46
+    */
47
+
48
+    .flash_begin : {
49
+        __flash_binary_start = .;
50
+    } > FLASH
51
+
52
+    .boot2 : {
53
+        __boot2_start__ = .;
54
+        KEEP (*(.boot2))
55
+        __boot2_end__ = .;
56
+    } > FLASH
57
+
58
+    ASSERT(__boot2_end__ - __boot2_start__ == 256,
59
+        "ERROR: Pico second stage bootloader must be 256 bytes in size")
60
+
61
+    /*
62
+     * Name a section for the image header and app binary
63
+     * In combined builds, the contents will get replaced post-build
64
+     */
65
+    .app_hdr : {
66
+        . = ALIGN(4k);
67
+	__app_hdr = .;
68
+	LONG(0xdeaddead)
69
+	LONG(0)
70
+	LONG(0xdeaddead)
71
+    } > FLASH_IMGHDR
72
+
73
+    .app_bin : {
74
+        . = ALIGN(4k);
75
+	__app_bin = .;
76
+	LONG(0)
77
+    } > FLASH_APP
78
+
79
+    /* The second stage will always enter the image at the start of .text.
80
+       The debugger will use the ELF entry point, which is the _entry_point
81
+       symbol if present, otherwise defaults to start of .text.
82
+       This can be used to transfer control back to the bootrom on debugger
83
+       launches only, to perform proper flash setup.
84
+    */
85
+
86
+    .text : {
87
+        __logical_binary_start = .;
88
+        KEEP (*(.vectors))
89
+        KEEP (*(.binary_info_header))
90
+        __binary_info_header_end = .;
91
+        KEEP (*(.reset))
92
+        /* TODO revisit this now memset/memcpy/float in ROM */
93
+        /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
94
+         * FLASH ... we will include any thing excluded here in .data below by default */
95
+        *(.init)
96
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
97
+        *(.fini)
98
+        /* Pull all c'tors into .text */
99
+        *crtbegin.o(.ctors)
100
+        *crtbegin?.o(.ctors)
101
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
102
+        *(SORT(.ctors.*))
103
+        *(.ctors)
104
+        /* Followed by destructors */
105
+        *crtbegin.o(.dtors)
106
+        *crtbegin?.o(.dtors)
107
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
108
+        *(SORT(.dtors.*))
109
+        *(.dtors)
110
+
111
+        *(.eh_frame*)
112
+        . = ALIGN(4);
113
+    } > FLASH
114
+
115
+    .rodata : {
116
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
117
+        . = ALIGN(4);
118
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
119
+        . = ALIGN(4);
120
+    } > FLASH
121
+
122
+    .ARM.extab :
123
+    {
124
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
125
+    } > FLASH
126
+
127
+    __exidx_start = .;
128
+    .ARM.exidx :
129
+    {
130
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
131
+    } > FLASH
132
+    __exidx_end = .;
133
+
134
+    /* Machine inspectable binary information */
135
+    . = ALIGN(4);
136
+    __binary_info_start = .;
137
+    .binary_info :
138
+    {
139
+        KEEP(*(.binary_info.keep.*))
140
+        *(.binary_info.*)
141
+    } > FLASH
142
+    __binary_info_end = .;
143
+    . = ALIGN(4);
144
+
145
+    /* End of .text-like segments */
146
+    __etext = .;
147
+
148
+   .ram_vector_table (COPY): {
149
+        *(.ram_vector_table)
150
+    } > RAM
151
+
152
+    .data : {
153
+        __data_start__ = .;
154
+        *(vtable)
155
+
156
+        *(.time_critical*)
157
+
158
+        /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
159
+        *(.text*)
160
+        . = ALIGN(4);
161
+        *(.rodata*)
162
+        . = ALIGN(4);
163
+
164
+        *(.data*)
165
+
166
+        . = ALIGN(4);
167
+        *(.after_data.*)
168
+        . = ALIGN(4);
169
+        /* preinit data */
170
+        PROVIDE_HIDDEN (__mutex_array_start = .);
171
+        KEEP(*(SORT(.mutex_array.*)))
172
+        KEEP(*(.mutex_array))
173
+        PROVIDE_HIDDEN (__mutex_array_end = .);
174
+
175
+        . = ALIGN(4);
176
+        /* preinit data */
177
+        PROVIDE_HIDDEN (__preinit_array_start = .);
178
+        KEEP(*(SORT(.preinit_array.*)))
179
+        KEEP(*(.preinit_array))
180
+        PROVIDE_HIDDEN (__preinit_array_end = .);
181
+
182
+        . = ALIGN(4);
183
+        /* init data */
184
+        PROVIDE_HIDDEN (__init_array_start = .);
185
+        KEEP(*(SORT(.init_array.*)))
186
+        KEEP(*(.init_array))
187
+        PROVIDE_HIDDEN (__init_array_end = .);
188
+
189
+        . = ALIGN(4);
190
+        /* finit data */
191
+        PROVIDE_HIDDEN (__fini_array_start = .);
192
+        *(SORT(.fini_array.*))
193
+        *(.fini_array)
194
+        PROVIDE_HIDDEN (__fini_array_end = .);
195
+
196
+        *(.jcr)
197
+        . = ALIGN(4);
198
+        /* All data end */
199
+        __data_end__ = .;
200
+    } > RAM AT> FLASH
201
+
202
+    .uninitialized_data (COPY): {
203
+        . = ALIGN(4);
204
+        *(.uninitialized_data*)
205
+    } > RAM
206
+
207
+    /* Start and end symbols must be word-aligned */
208
+    .scratch_x : {
209
+        __scratch_x_start__ = .;
210
+        *(.scratch_x.*)
211
+        . = ALIGN(4);
212
+        __scratch_x_end__ = .;
213
+    } > SCRATCH_X AT > FLASH
214
+    __scratch_x_source__ = LOADADDR(.scratch_x);
215
+
216
+    .scratch_y : {
217
+        __scratch_y_start__ = .;
218
+        *(.scratch_y.*)
219
+        . = ALIGN(4);
220
+        __scratch_y_end__ = .;
221
+    } > SCRATCH_Y AT > FLASH
222
+    __scratch_y_source__ = LOADADDR(.scratch_y);
223
+
224
+    .bss  : {
225
+        . = ALIGN(4);
226
+        __bss_start__ = .;
227
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
228
+        *(COMMON)
229
+        . = ALIGN(4);
230
+        __bss_end__ = .;
231
+    } > RAM
232
+
233
+    .heap (COPY):
234
+    {
235
+        __end__ = .;
236
+        end = __end__;
237
+        *(.heap*)
238
+        __HeapLimit = .;
239
+    } > RAM
240
+
241
+    /* .stack*_dummy section doesn't contains any symbols. It is only
242
+     * used for linker to calculate size of stack sections, and assign
243
+     * values to stack symbols later
244
+     *
245
+     * stack1 section may be empty/missing if platform_launch_core1 is not used */
246
+
247
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
248
+     * stack is not used then all of SCRATCH_X is free.
249
+     */
250
+    .stack1_dummy (COPY):
251
+    {
252
+        *(.stack1*)
253
+    } > SCRATCH_X
254
+    .stack_dummy (COPY):
255
+    {
256
+        *(.stack*)
257
+    } > SCRATCH_Y
258
+
259
+    .flash_end : {
260
+        __flash_binary_end = .;
261
+    } > FLASH
262
+
263
+    /* stack limit is poorly named, but historically is maximum heap ptr */
264
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
265
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
266
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
267
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
268
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
269
+    PROVIDE(__stack = __StackTop);
270
+
271
+    /* Check if data + heap + stack exceeds RAM limit */
272
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
273
+
274
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
275
+    /* todo assert on extra code */
276
+}

+ 248
- 0
combined.ld View File

@@ -0,0 +1,248 @@
1
+/* Based on GCC ARM embedded samples.
2
+   Defines the following symbols for use by code:
3
+    __exidx_start
4
+    __exidx_end
5
+    __etext
6
+    __data_start__
7
+    __preinit_array_start
8
+    __preinit_array_end
9
+    __init_array_start
10
+    __init_array_end
11
+    __fini_array_start
12
+    __fini_array_end
13
+    __data_end__
14
+    __bss_start__
15
+    __bss_end__
16
+    __end__
17
+    end
18
+    __HeapLimit
19
+    __StackLimit
20
+    __StackTop
21
+    __stack (== StackTop)
22
+*/
23
+
24
+MEMORY
25
+{
26
+    FLASH_BL(rx) : ORIGIN = 0x10000000, LENGTH = 360k
27
+    FLASH_IMGHDR(rx) : ORIGIN = 0x10000000 + 360k, LENGTH = 4k
28
+    FLASH_APP(rx) : ORIGIN = 0x10000000 + 364k, LENGTH = 2048k - 364k
29
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
30
+    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
31
+    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
32
+}
33
+
34
+ENTRY(_entry_point)
35
+
36
+SECTIONS
37
+{
38
+    .flash_begin : {
39
+        __flash_binary_start = .;
40
+    } > FLASH_APP
41
+
42
+    /* Insert boot3, which is the combined boot2 + boot3 */
43
+    .boot3 : {
44
+        KEEP (*(.boot3))
45
+    } > FLASH_BL
46
+
47
+    /*
48
+     * Name a section for the image header.
49
+     * The contents will get replaced post-build
50
+     */
51
+    .app_hdr : {
52
+	LONG(0xdeaddead)
53
+	LONG(0)
54
+	LONG(0xdeaddead)
55
+    } > FLASH_IMGHDR
56
+
57
+    .text : {
58
+        __logical_binary_start = .;
59
+        KEEP (*(.vectors))
60
+        KEEP (*(.binary_info_header))
61
+        __binary_info_header_end = .;
62
+        KEEP (*(.reset))
63
+        /* TODO revisit this now memset/memcpy/float in ROM */
64
+        /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
65
+         * FLASH ... we will include any thing excluded here in .data below by default */
66
+        *(.init)
67
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
68
+        *(.fini)
69
+        /* Pull all c'tors into .text */
70
+        *crtbegin.o(.ctors)
71
+        *crtbegin?.o(.ctors)
72
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
73
+        *(SORT(.ctors.*))
74
+        *(.ctors)
75
+        /* Followed by destructors */
76
+        *crtbegin.o(.dtors)
77
+        *crtbegin?.o(.dtors)
78
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
79
+        *(SORT(.dtors.*))
80
+        *(.dtors)
81
+
82
+        *(.eh_frame*)
83
+        . = ALIGN(4);
84
+    } > FLASH_APP
85
+
86
+    .rodata : {
87
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
88
+        . = ALIGN(4);
89
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
90
+        . = ALIGN(4);
91
+    } > FLASH_APP
92
+
93
+    .ARM.extab :
94
+    {
95
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
96
+    } > FLASH_APP
97
+
98
+    __exidx_start = .;
99
+    .ARM.exidx :
100
+    {
101
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
102
+    } > FLASH_APP
103
+    __exidx_end = .;
104
+
105
+    /* Machine inspectable binary information */
106
+    . = ALIGN(4);
107
+    __binary_info_start = .;
108
+    .binary_info :
109
+    {
110
+        KEEP(*(.binary_info.keep.*))
111
+        *(.binary_info.*)
112
+    } > FLASH_APP
113
+    __binary_info_end = .;
114
+    . = ALIGN(4);
115
+
116
+    /* End of .text-like segments */
117
+    __etext = .;
118
+
119
+   .ram_vector_table (COPY): {
120
+        *(.ram_vector_table)
121
+    } > RAM
122
+
123
+    .data : {
124
+        __data_start__ = .;
125
+        *(vtable)
126
+
127
+        *(.time_critical*)
128
+
129
+        /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
130
+        *(.text*)
131
+        . = ALIGN(4);
132
+        *(.rodata*)
133
+        . = ALIGN(4);
134
+
135
+        *(.data*)
136
+
137
+        . = ALIGN(4);
138
+        *(.after_data.*)
139
+        . = ALIGN(4);
140
+        /* preinit data */
141
+        PROVIDE_HIDDEN (__mutex_array_start = .);
142
+        KEEP(*(SORT(.mutex_array.*)))
143
+        KEEP(*(.mutex_array))
144
+        PROVIDE_HIDDEN (__mutex_array_end = .);
145
+
146
+        . = ALIGN(4);
147
+        /* preinit data */
148
+        PROVIDE_HIDDEN (__preinit_array_start = .);
149
+        KEEP(*(SORT(.preinit_array.*)))
150
+        KEEP(*(.preinit_array))
151
+        PROVIDE_HIDDEN (__preinit_array_end = .);
152
+
153
+        . = ALIGN(4);
154
+        /* init data */
155
+        PROVIDE_HIDDEN (__init_array_start = .);
156
+        KEEP(*(SORT(.init_array.*)))
157
+        KEEP(*(.init_array))
158
+        PROVIDE_HIDDEN (__init_array_end = .);
159
+
160
+        . = ALIGN(4);
161
+        /* finit data */
162
+        PROVIDE_HIDDEN (__fini_array_start = .);
163
+        *(SORT(.fini_array.*))
164
+        *(.fini_array)
165
+        PROVIDE_HIDDEN (__fini_array_end = .);
166
+
167
+        *(.jcr)
168
+        . = ALIGN(4);
169
+        /* All data end */
170
+        __data_end__ = .;
171
+    } > RAM AT> FLASH_APP
172
+
173
+    .uninitialized_data (COPY): {
174
+        . = ALIGN(4);
175
+        *(.uninitialized_data*)
176
+    } > RAM
177
+
178
+    /* Start and end symbols must be word-aligned */
179
+    .scratch_x : {
180
+        __scratch_x_start__ = .;
181
+        *(.scratch_x.*)
182
+        . = ALIGN(4);
183
+        __scratch_x_end__ = .;
184
+    } > SCRATCH_X AT > FLASH_APP
185
+    __scratch_x_source__ = LOADADDR(.scratch_x);
186
+
187
+    .scratch_y : {
188
+        __scratch_y_start__ = .;
189
+        *(.scratch_y.*)
190
+        . = ALIGN(4);
191
+        __scratch_y_end__ = .;
192
+    } > SCRATCH_Y AT > FLASH_APP
193
+    __scratch_y_source__ = LOADADDR(.scratch_y);
194
+
195
+    .bss  : {
196
+        . = ALIGN(4);
197
+        __bss_start__ = .;
198
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
199
+        *(COMMON)
200
+        . = ALIGN(4);
201
+        __bss_end__ = .;
202
+    } > RAM
203
+
204
+    .heap (COPY):
205
+    {
206
+        __end__ = .;
207
+        end = __end__;
208
+        *(.heap*)
209
+        __HeapLimit = .;
210
+    } > RAM
211
+
212
+    /* .stack*_dummy section doesn't contains any symbols. It is only
213
+     * used for linker to calculate size of stack sections, and assign
214
+     * values to stack symbols later
215
+     *
216
+     * stack1 section may be empty/missing if platform_launch_core1 is not used */
217
+
218
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
219
+     * stack is not used then all of SCRATCH_X is free.
220
+     */
221
+    .stack1_dummy (COPY):
222
+    {
223
+        *(.stack1*)
224
+    } > SCRATCH_X
225
+    .stack_dummy (COPY):
226
+    {
227
+        *(.stack*)
228
+    } > SCRATCH_Y
229
+
230
+    .flash_end : {
231
+        __flash_binary_end = .;
232
+    } > FLASH_APP
233
+
234
+    /* stack limit is poorly named, but historically is maximum heap ptr */
235
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
236
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
237
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
238
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
239
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
240
+    PROVIDE(__stack = __StackTop);
241
+
242
+    /* Check if data + heap + stack exceeds RAM limit */
243
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
244
+
245
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
246
+    /* todo assert on extra code */
247
+}
248
+

+ 59
- 0
gen_imghdr.py View File

@@ -0,0 +1,59 @@
1
+#!/usr/bin/env python3
2
+# Derived from pad_checksum in the Pico SDK, which carries the following
3
+# LICENSE.txt:
4
+# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
5
+# 
6
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
+# following conditions are met:
8
+# 
9
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
10
+#    disclaimer.
11
+# 
12
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
13
+#    disclaimer in the documentation and/or other materials provided with the distribution.
14
+# 
15
+# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
16
+#    derived from this software without specific prior written permission.
17
+# 
18
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+import argparse
27
+import binascii
28
+import struct
29
+import sys
30
+
31
+def any_int(x):
32
+    try:
33
+        return int(x, 0)
34
+    except:
35
+        raise argparse.ArgumentTypeError("expected an integer, not '{!r}'".format(x))
36
+
37
+parser = argparse.ArgumentParser()
38
+parser.add_argument("ifile", help="Input application binary (binary)")
39
+parser.add_argument("ofile", help="Output header file (binary)")
40
+parser.add_argument("-a", "--addr", help="Load address of the application image",
41
+                    type=any_int, default=0x10004000)
42
+args = parser.parse_args()
43
+
44
+try:
45
+    idata = open(args.ifile, "rb").read()
46
+except:
47
+    sys.exit("Could not open input file '{}'".format(args.ifile))
48
+
49
+vtor = args.addr
50
+size = len(idata)
51
+crc = binascii.crc32(idata)
52
+
53
+odata = vtor.to_bytes(4, byteorder='little') + size.to_bytes(4, byteorder='little') + crc.to_bytes(4, byteorder='little')
54
+
55
+try:
56
+    with open(args.ofile, "wb") as ofile:
57
+        ofile.write(odata)
58
+except:
59
+    sys.exit("Could not open output file '{}'".format(args.ofile))

+ 53
- 0
mkasm.py View File

@@ -0,0 +1,53 @@
1
+#!/usr/bin/env python3
2
+# Derived from pad_checksum in the Pico SDK, which carries the following
3
+# LICENSE.txt:
4
+# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
5
+#
6
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
+# following conditions are met:
8
+#
9
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
10
+#    disclaimer.
11
+#
12
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
13
+#    disclaimer in the documentation and/or other materials provided with the distribution.
14
+#
15
+# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
16
+#    derived from this software without specific prior written permission.
17
+#
18
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+import argparse
27
+import binascii
28
+import struct
29
+import sys
30
+
31
+parser = argparse.ArgumentParser()
32
+parser.add_argument("ifile", help="Input file (binary)")
33
+parser.add_argument("ofile", help="Output file (assembly)")
34
+args = parser.parse_args()
35
+
36
+try:
37
+    idata = open(args.ifile, "rb").read()
38
+except:
39
+    sys.exit("Could not open input file '{}'".format(args.ifile))
40
+
41
+odata = idata
42
+
43
+try:
44
+    with open(args.ofile, "w") as ofile:
45
+        ofile.write("// ASM-ified version of: {}\n\n".format(args.ifile))
46
+        ofile.write(".cpu cortex-m0plus\n")
47
+        ofile.write(".thumb\n\n")
48
+        ofile.write(".section .boot3, \"ax\"\n\n")
49
+        for offs in range(0, len(odata), 16):
50
+            chunk = odata[offs:min(offs + 16, len(odata))]
51
+            ofile.write(".byte {}\n".format(", ".join("0x{:02x}".format(b) for b in chunk)))
52
+except:
53
+    sys.exit("Could not open output file '{}'".format(args.ofile))

+ 234
- 0
standalone.ld View File

@@ -0,0 +1,234 @@
1
+/* Based on GCC ARM embedded samples.
2
+   Defines the following symbols for use by code:
3
+    __exidx_start
4
+    __exidx_end
5
+    __etext
6
+    __data_start__
7
+    __preinit_array_start
8
+    __preinit_array_end
9
+    __init_array_start
10
+    __init_array_end
11
+    __fini_array_start
12
+    __fini_array_end
13
+    __data_end__
14
+    __bss_start__
15
+    __bss_end__
16
+    __end__
17
+    end
18
+    __HeapLimit
19
+    __StackLimit
20
+    __StackTop
21
+    __stack (== StackTop)
22
+*/
23
+
24
+/* Skip 364kB at the start of flash, that's where the bootloader is */
25
+MEMORY
26
+{
27
+    FLASH(rx) : ORIGIN = 0x10000000 + 364k, LENGTH = 2048k - 364k
28
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
29
+    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
30
+    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
31
+}
32
+
33
+ENTRY(_entry_point)
34
+
35
+SECTIONS
36
+{
37
+    .flash_begin : {
38
+        __flash_binary_start = .;
39
+    } > FLASH
40
+
41
+    /* boot2 would normally go here, but we don't want it */
42
+
43
+    .text : {
44
+        __logical_binary_start = .;
45
+        KEEP (*(.vectors))
46
+        KEEP (*(.binary_info_header))
47
+        __binary_info_header_end = .;
48
+        KEEP (*(.reset))
49
+        /* TODO revisit this now memset/memcpy/float in ROM */
50
+        /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
51
+         * FLASH ... we will include any thing excluded here in .data below by default */
52
+        *(.init)
53
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
54
+        *(.fini)
55
+        /* Pull all c'tors into .text */
56
+        *crtbegin.o(.ctors)
57
+        *crtbegin?.o(.ctors)
58
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
59
+        *(SORT(.ctors.*))
60
+        *(.ctors)
61
+        /* Followed by destructors */
62
+        *crtbegin.o(.dtors)
63
+        *crtbegin?.o(.dtors)
64
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
65
+        *(SORT(.dtors.*))
66
+        *(.dtors)
67
+
68
+        *(.eh_frame*)
69
+        . = ALIGN(4);
70
+    } > FLASH
71
+
72
+    .rodata : {
73
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
74
+        . = ALIGN(4);
75
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
76
+        . = ALIGN(4);
77
+    } > FLASH
78
+
79
+    .ARM.extab :
80
+    {
81
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
82
+    } > FLASH
83
+
84
+    __exidx_start = .;
85
+    .ARM.exidx :
86
+    {
87
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
88
+    } > FLASH
89
+    __exidx_end = .;
90
+
91
+    /* Machine inspectable binary information */
92
+    . = ALIGN(4);
93
+    __binary_info_start = .;
94
+    .binary_info :
95
+    {
96
+        KEEP(*(.binary_info.keep.*))
97
+        *(.binary_info.*)
98
+    } > FLASH
99
+    __binary_info_end = .;
100
+    . = ALIGN(4);
101
+
102
+    /* End of .text-like segments */
103
+    __etext = .;
104
+
105
+   .ram_vector_table (COPY): {
106
+        *(.ram_vector_table)
107
+    } > RAM
108
+
109
+    .data : {
110
+        __data_start__ = .;
111
+        *(vtable)
112
+
113
+        *(.time_critical*)
114
+
115
+        /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
116
+        *(.text*)
117
+        . = ALIGN(4);
118
+        *(.rodata*)
119
+        . = ALIGN(4);
120
+
121
+        *(.data*)
122
+
123
+        . = ALIGN(4);
124
+        *(.after_data.*)
125
+        . = ALIGN(4);
126
+        /* preinit data */
127
+        PROVIDE_HIDDEN (__mutex_array_start = .);
128
+        KEEP(*(SORT(.mutex_array.*)))
129
+        KEEP(*(.mutex_array))
130
+        PROVIDE_HIDDEN (__mutex_array_end = .);
131
+
132
+        . = ALIGN(4);
133
+        /* preinit data */
134
+        PROVIDE_HIDDEN (__preinit_array_start = .);
135
+        KEEP(*(SORT(.preinit_array.*)))
136
+        KEEP(*(.preinit_array))
137
+        PROVIDE_HIDDEN (__preinit_array_end = .);
138
+
139
+        . = ALIGN(4);
140
+        /* init data */
141
+        PROVIDE_HIDDEN (__init_array_start = .);
142
+        KEEP(*(SORT(.init_array.*)))
143
+        KEEP(*(.init_array))
144
+        PROVIDE_HIDDEN (__init_array_end = .);
145
+
146
+        . = ALIGN(4);
147
+        /* finit data */
148
+        PROVIDE_HIDDEN (__fini_array_start = .);
149
+        *(SORT(.fini_array.*))
150
+        *(.fini_array)
151
+        PROVIDE_HIDDEN (__fini_array_end = .);
152
+
153
+        *(.jcr)
154
+        . = ALIGN(4);
155
+        /* All data end */
156
+        __data_end__ = .;
157
+    } > RAM AT> FLASH
158
+
159
+    .uninitialized_data (COPY): {
160
+        . = ALIGN(4);
161
+        *(.uninitialized_data*)
162
+    } > RAM
163
+
164
+    /* Start and end symbols must be word-aligned */
165
+    .scratch_x : {
166
+        __scratch_x_start__ = .;
167
+        *(.scratch_x.*)
168
+        . = ALIGN(4);
169
+        __scratch_x_end__ = .;
170
+    } > SCRATCH_X AT > FLASH
171
+    __scratch_x_source__ = LOADADDR(.scratch_x);
172
+
173
+    .scratch_y : {
174
+        __scratch_y_start__ = .;
175
+        *(.scratch_y.*)
176
+        . = ALIGN(4);
177
+        __scratch_y_end__ = .;
178
+    } > SCRATCH_Y AT > FLASH
179
+    __scratch_y_source__ = LOADADDR(.scratch_y);
180
+
181
+    .bss  : {
182
+        . = ALIGN(4);
183
+        __bss_start__ = .;
184
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
185
+        *(COMMON)
186
+        . = ALIGN(4);
187
+        __bss_end__ = .;
188
+    } > RAM
189
+
190
+    .heap (COPY):
191
+    {
192
+        __end__ = .;
193
+        end = __end__;
194
+        *(.heap*)
195
+        __HeapLimit = .;
196
+    } > RAM
197
+
198
+    /* .stack*_dummy section doesn't contains any symbols. It is only
199
+     * used for linker to calculate size of stack sections, and assign
200
+     * values to stack symbols later
201
+     *
202
+     * stack1 section may be empty/missing if platform_launch_core1 is not used */
203
+
204
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
205
+     * stack is not used then all of SCRATCH_X is free.
206
+     */
207
+    .stack1_dummy (COPY):
208
+    {
209
+        *(.stack1*)
210
+    } > SCRATCH_X
211
+    .stack_dummy (COPY):
212
+    {
213
+        *(.stack*)
214
+    } > SCRATCH_Y
215
+
216
+    .flash_end : {
217
+        __flash_binary_end = .;
218
+    } > FLASH
219
+
220
+    /* stack limit is poorly named, but historically is maximum heap ptr */
221
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
222
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
223
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
224
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
225
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
226
+    PROVIDE(__stack = __StackTop);
227
+
228
+    /* Check if data + heap + stack exceeds RAM limit */
229
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
230
+
231
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
232
+    /* todo assert on extra code */
233
+}
234
+

Loading…
Cancel
Save