mirror of
https://github.com/raspberrypi/pico-sdk.git
synced 2026-03-14 21:19:43 +01:00
Merge 9c0ed0cc45 into bc5481455f
This commit is contained in:
commit
4e0795a151
62 changed files with 1568 additions and 2051 deletions
|
|
@ -217,10 +217,10 @@ string_flag(
|
|||
build_setting_default = "Debug",
|
||||
)
|
||||
|
||||
# PICO_BAZEL_CONFIG: PICO_DEFAULT_LINKER_SCRIPT, [Bazel only] The library that provides a linker script to link into all binaries, default=//src/rp2_common/pico_crt0:default_linker_script, group=pico_standard_link
|
||||
# PICO_BAZEL_CONFIG: PICO_DEFAULT_LINKER_SCRIPT, [Bazel only] The library that provides a linker script to link into all binaries, default=//src/rp2_common/pico_standard_link:default_linker_script, group=pico_standard_link
|
||||
label_flag(
|
||||
name = "PICO_DEFAULT_LINKER_SCRIPT",
|
||||
build_setting_default = "//src/rp2_common/pico_crt0:default_linker_script",
|
||||
build_setting_default = "//src/rp2_common/pico_standard_link:default_linker_script",
|
||||
)
|
||||
|
||||
# PICO_BAZEL_CONFIG: PICO_NO_TARGET_NAME, Don't define PICO_TARGET_NAME, type=bool, default=0, group=build
|
||||
|
|
|
|||
49
bazel/util/pico_linker_scripts.bzl
Normal file
49
bazel/util/pico_linker_scripts.bzl
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain")
|
||||
|
||||
def _include_linker_script_dir_impl(ctx):
|
||||
link_include_dir = str(ctx.label.package)
|
||||
depset_direct = ["-L" + str(link_include_dir)]
|
||||
if len(ctx.files.use_scripts):
|
||||
for script in ctx.files.use_scripts:
|
||||
depset_direct.append("-T" + str(script.path))
|
||||
|
||||
linking_inputs = cc_common.create_linker_input(
|
||||
owner = ctx.label,
|
||||
user_link_flags = depset(
|
||||
direct = depset_direct,
|
||||
),
|
||||
)
|
||||
return [
|
||||
CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))),
|
||||
]
|
||||
|
||||
include_linker_script_dir = rule(
|
||||
implementation = _include_linker_script_dir_impl,
|
||||
attrs = {
|
||||
"use_scripts": attr.label_list(allow_files = [".ld"]),
|
||||
},
|
||||
toolchains = use_cpp_toolchain(),
|
||||
fragments = ["cpp"],
|
||||
)
|
||||
|
||||
def _use_linker_script_file_impl(ctx):
|
||||
link_file = ctx.file.script.path
|
||||
|
||||
linking_inputs = cc_common.create_linker_input(
|
||||
owner = ctx.label,
|
||||
user_link_flags = depset(
|
||||
direct = ["-T" + str(link_file)],
|
||||
),
|
||||
)
|
||||
return [
|
||||
CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))),
|
||||
]
|
||||
|
||||
use_linker_script_file = rule(
|
||||
implementation = _use_linker_script_file_impl,
|
||||
attrs = {
|
||||
"script": attr.label(mandatory = True, allow_single_file = [".ld"]),
|
||||
},
|
||||
toolchains = use_cpp_toolchain(),
|
||||
fragments = ["cpp"],
|
||||
)
|
||||
|
|
@ -28,6 +28,7 @@ pico_add_subdirectory(common/hardware_claim)
|
|||
#
|
||||
# RP2040/RP2350 specific From standard build variants
|
||||
pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform)
|
||||
pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform_link)
|
||||
pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_regs)
|
||||
pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_structs)
|
||||
pico_add_subdirectory(${RP2_VARIANT_DIR}/boot_stage2)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
|||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file")
|
||||
|
||||
exports_files(
|
||||
[
|
||||
"memmap_blocked_ram.ld",
|
||||
|
|
@ -11,23 +13,36 @@ exports_files(
|
|||
],
|
||||
)
|
||||
|
||||
# It's possible to set linker scripts globally or on a per-binary basis.
|
||||
#
|
||||
# Setting globally:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your
|
||||
# desired linker script.
|
||||
#
|
||||
# Setting per-binary:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib
|
||||
# * Manually add your desired linker script to each cc_binary.
|
||||
use_linker_script_file(
|
||||
name = "memmap_default_args",
|
||||
script = "memmap_default.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_blocked_ram_args",
|
||||
script = "memmap_blocked_ram.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_copy_to_ram_args",
|
||||
script = "memmap_copy_to_ram.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_no_flash_args",
|
||||
script = "memmap_no_flash.ld",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "default_linker_script",
|
||||
linkopts = ["-T$(location memmap_default.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2040"],
|
||||
deps = [
|
||||
"memmap_default.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link:default_flash_region",
|
||||
"memmap_default.ld",
|
||||
"memmap_default_args",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -35,12 +50,14 @@ cc_library(
|
|||
cc_library(
|
||||
name = "blocked_ram_linker_script",
|
||||
defines = ["PICO_USE_BLOCKED_RAM=1"],
|
||||
linkopts = ["-T$(location memmap_blocked_ram.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2040"],
|
||||
deps = [
|
||||
"memmap_blocked_ram.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link:default_flash_region",
|
||||
"memmap_blocked_ram.ld",
|
||||
"memmap_blocked_ram_args",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -48,12 +65,14 @@ cc_library(
|
|||
cc_library(
|
||||
name = "copy_to_ram_linker_script",
|
||||
defines = ["PICO_COPY_TO_RAM=1"],
|
||||
linkopts = ["-T$(location memmap_copy_to_ram.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2040"],
|
||||
deps = [
|
||||
"memmap_copy_to_ram.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link:default_flash_region",
|
||||
"memmap_copy_to_ram.ld",
|
||||
"memmap_copy_to_ram_args",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -61,10 +80,12 @@ cc_library(
|
|||
cc_library(
|
||||
name = "no_flash_linker_script",
|
||||
defines = ["PICO_NO_FLASH=1"],
|
||||
linkopts = ["-T$(location memmap_no_flash.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2040"],
|
||||
deps = [
|
||||
"memmap_no_flash.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"memmap_no_flash.ld",
|
||||
"memmap_no_flash_args",
|
||||
],
|
||||
)
|
||||
6
src/rp2040/pico_platform_link/CMakeLists.txt
Normal file
6
src/rp2040/pico_platform_link/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH)
|
||||
if (NOT PICO_LINKER_SCRIPT_PATH)
|
||||
set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
endif()
|
||||
|
||||
pico_promote_common_scope_vars()
|
||||
4
src/rp2040/pico_platform_link/memmap_blocked_ram.ld
Normal file
4
src/rp2040/pico_platform_link/memmap_blocked_ram.ld
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* Use blocked ram */
|
||||
RAM_ORIGIN = 0x21000000;
|
||||
|
||||
INCLUDE "memmap_default.ld"
|
||||
1
src/rp2040/pico_platform_link/memmap_copy_to_ram.ld
Normal file
1
src/rp2040/pico_platform_link/memmap_copy_to_ram.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_copy_to_ram.ld"
|
||||
1
src/rp2040/pico_platform_link/memmap_default.ld
Normal file
1
src/rp2040/pico_platform_link/memmap_default.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_default.ld"
|
||||
1
src/rp2040/pico_platform_link/memmap_no_flash.ld
Normal file
1
src/rp2040/pico_platform_link/memmap_no_flash.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_no_flash.ld"
|
||||
33
src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel
Normal file
33
src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir")
|
||||
|
||||
exports_files(
|
||||
[
|
||||
"default_locations.ld",
|
||||
"section_copy_to_ram_text.ld",
|
||||
"section_default_text.ld",
|
||||
"section_no_flash_text.ld",
|
||||
"section_platform_end.ld",
|
||||
]
|
||||
)
|
||||
|
||||
include_linker_script_dir(
|
||||
name = "rp2040_linker_script_args",
|
||||
use_scripts = ["default_locations.ld"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "rp2040_linker_scripts",
|
||||
target_compatible_with = ["//bazel/constraint:rp2040"],
|
||||
deps = [
|
||||
"default_locations.ld",
|
||||
"section_copy_to_ram_text.ld",
|
||||
"section_default_text.ld",
|
||||
"section_no_flash_text.ld",
|
||||
"section_platform_end.ld",
|
||||
"rp2040_linker_script_args",
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
RAM_ORIGIN_DEFAULT = 0x20000000;
|
||||
RAM_LENGTH_DEFAULT = 256k;
|
||||
SCRATCH_X_ORIGIN_DEFAULT = 0x20040000;
|
||||
SCRATCH_X_LENGTH_DEFAULT = 4k;
|
||||
SCRATCH_Y_ORIGIN_DEFAULT = 0x20041000;
|
||||
SCRATCH_Y_LENGTH_DEFAULT = 4k;
|
||||
XIP_RAM_ORIGIN_DEFAULT = 0x15000000;
|
||||
XIP_RAM_LENGTH_DEFAULT = 16k;
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.flashtext : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* Vector table goes first in RAM, to avoid large alignment hole */
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.text : {
|
||||
__ram_text_start__ = .;
|
||||
*(.init)
|
||||
*(.text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
__ram_text_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
__ram_text_source__ = LOADADDR(.text);
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* Note in NO_FLASH builds the entry point for both the bootrom, and debugger
|
||||
entry (ELF entry point), are *first* in the image, and the vector table
|
||||
follows immediately afterward. This is because the bootrom enters RAM
|
||||
binaries directly at their lowest address (preferring main RAM over XIP
|
||||
cache-as-SRAM if both are used).
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
__reset_end = .;
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
. = ALIGN(256);
|
||||
KEEP (*(.vectors))
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.init)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
} > RAM
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > RAM
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > RAM
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > RAM
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
|||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file")
|
||||
|
||||
exports_files(
|
||||
[
|
||||
"memmap_copy_to_ram.ld",
|
||||
|
|
@ -10,23 +12,36 @@ exports_files(
|
|||
],
|
||||
)
|
||||
|
||||
# It's possible to set linker scripts globally or on a per-binary basis.
|
||||
#
|
||||
# Setting globally:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your
|
||||
# desired linker script.
|
||||
#
|
||||
# Setting per-binary:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib
|
||||
# * Manually add your desired linker script to each cc_binary.
|
||||
use_linker_script_file(
|
||||
name = "memmap_default_args",
|
||||
script = "memmap_default.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_blocked_ram_args",
|
||||
script = "memmap_blocked_ram.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_copy_to_ram_args",
|
||||
script = "memmap_copy_to_ram.ld",
|
||||
)
|
||||
|
||||
use_linker_script_file(
|
||||
name = "memmap_no_flash_args",
|
||||
script = "memmap_no_flash.ld",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "default_linker_script",
|
||||
linkopts = ["-T$(location memmap_default.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2350"],
|
||||
deps = [
|
||||
"memmap_default.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link:default_flash_region",
|
||||
"memmap_default.ld",
|
||||
"memmap_default_args",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -34,12 +49,14 @@ cc_library(
|
|||
cc_library(
|
||||
name = "copy_to_ram_linker_script",
|
||||
defines = ["PICO_COPY_TO_RAM=1"],
|
||||
linkopts = ["-T$(location memmap_copy_to_ram.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2350"],
|
||||
deps = [
|
||||
"memmap_copy_to_ram.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link:default_flash_region",
|
||||
"memmap_copy_to_ram.ld",
|
||||
"memmap_copy_to_ram_args",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -47,10 +64,12 @@ cc_library(
|
|||
cc_library(
|
||||
name = "no_flash_linker_script",
|
||||
defines = ["PICO_NO_FLASH=1"],
|
||||
linkopts = ["-T$(location memmap_no_flash.ld)"],
|
||||
target_compatible_with = ["//bazel/constraint:rp2350"],
|
||||
deps = [
|
||||
"memmap_no_flash.ld",
|
||||
"//src/rp2_common/pico_crt0:no_warn_rwx_flag",
|
||||
"//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts",
|
||||
"//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts",
|
||||
"memmap_no_flash.ld",
|
||||
"memmap_no_flash_args",
|
||||
],
|
||||
)
|
||||
6
src/rp2350/pico_platform_link/CMakeLists.txt
Normal file
6
src/rp2350/pico_platform_link/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH)
|
||||
if (NOT PICO_LINKER_SCRIPT_PATH)
|
||||
set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
endif()
|
||||
|
||||
pico_promote_common_scope_vars()
|
||||
1
src/rp2350/pico_platform_link/memmap_copy_to_ram.ld
Normal file
1
src/rp2350/pico_platform_link/memmap_copy_to_ram.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_copy_to_ram.ld"
|
||||
1
src/rp2350/pico_platform_link/memmap_default.ld
Normal file
1
src/rp2350/pico_platform_link/memmap_default.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_default.ld"
|
||||
1
src/rp2350/pico_platform_link/memmap_no_flash.ld
Normal file
1
src/rp2350/pico_platform_link/memmap_no_flash.ld
Normal file
|
|
@ -0,0 +1 @@
|
|||
INCLUDE "memmap_no_flash.ld"
|
||||
27
src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel
Normal file
27
src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir")
|
||||
|
||||
exports_files(
|
||||
[
|
||||
"default_locations.ld",
|
||||
"section_platform_end.ld",
|
||||
]
|
||||
)
|
||||
|
||||
include_linker_script_dir(
|
||||
name = "rp2350_linker_script_args",
|
||||
use_scripts = ["default_locations.ld"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "rp2350_linker_scripts",
|
||||
target_compatible_with = ["//bazel/constraint:rp2350"],
|
||||
deps = [
|
||||
"default_locations.ld",
|
||||
"section_platform_end.ld",
|
||||
"rp2350_linker_script_args",
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
RAM_ORIGIN_DEFAULT = 0x20000000;
|
||||
RAM_LENGTH_DEFAULT = 512k;
|
||||
SCRATCH_X_ORIGIN_DEFAULT = 0x20080000;
|
||||
SCRATCH_X_LENGTH_DEFAULT = 4k;
|
||||
SCRATCH_Y_ORIGIN_DEFAULT = 0x20081000;
|
||||
SCRATCH_Y_LENGTH_DEFAULT = 4k;
|
||||
XIP_RAM_ORIGIN_DEFAULT = 0x13FFC000;
|
||||
XIP_RAM_LENGTH_DEFAULT = 16k;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
SECTIONS
|
||||
{
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
|
||||
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
|
||||
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
|
@ -3,48 +3,13 @@ load("//bazel:defs.bzl", "compatible_with_rp2")
|
|||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
alias(
|
||||
name = "default_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:default_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:default_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "blocked_ram_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:blocked_ram_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "copy_to_ram_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:copy_to_ram_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:copy_to_ram_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "no_flash_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:no_flash_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:no_flash_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "no_warn_rwx_flag",
|
||||
linkopts = select({
|
||||
"//bazel/constraint:pico_toolchain_gcc_enabled": ["-Wl,--no-warn-rwx-segments"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
visibility = [":__subpackages__"],
|
||||
visibility = ["//src:__subpackages__"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,4 @@ if (NOT TARGET pico_crt0)
|
|||
target_link_libraries(pico_crt0 INTERFACE boot_picobin_headers pico_bootrom_headers)
|
||||
endif()
|
||||
|
||||
pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH)
|
||||
if (NOT PICO_LINKER_SCRIPT_PATH)
|
||||
set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}/${PICO_CHIP})
|
||||
endif()
|
||||
|
||||
pico_promote_common_scope_vars()
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.flashtext : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* Vector table goes first in RAM, to avoid large alignment hole */
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.text : {
|
||||
__ram_text_start__ = .;
|
||||
*(.init)
|
||||
*(.text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
__ram_text_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
__ram_text_source__ = LOADADDR(.text);
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Note in NO_FLASH builds the entry point for both the bootrom, and debugger
|
||||
entry (ELF entry point), are *first* in the image, and the vector table
|
||||
follows immediately afterward. This is because the bootrom enters RAM
|
||||
binaries directly at their lowest address (preferring main RAM over XIP
|
||||
cache-as-SRAM if both are used).
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
__reset_end = .;
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
. = ALIGN(256);
|
||||
KEEP (*(.vectors))
|
||||
*(.time_critical*)
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.init)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
} > RAM
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > RAM
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > RAM
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > RAM
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* On Arm, the bootrom expects a VT at the start of the
|
||||
image by default; on RISC-V, the default is to enter the image at its
|
||||
lowest address, so an IMAGE_DEF item is required to specify the
|
||||
nondefault entry point. */
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
/* The bootrom will enter the image at the point indicated in your
|
||||
IMAGE_DEF, which is usually the reset handler of your vector table.
|
||||
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol, and in our case is *different from the bootrom's entry point.*
|
||||
This is used to go back through the bootrom on debugger launches only,
|
||||
to perform the same initial flash setup that would be performed on a
|
||||
cold boot.
|
||||
*/
|
||||
|
||||
.flashtext : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
/* Note the boot2 section is optional, and should be discarded if there is
|
||||
no reference to it *inside* the binary, as it is not called by the
|
||||
bootrom. (The bootrom performs a simple best-effort XIP setup and
|
||||
leaves it to the binary to do anything more sophisticated.) However
|
||||
there is still a size limit of 256 bytes, to ensure the boot2 can be
|
||||
stored in boot RAM.
|
||||
|
||||
Really this is a "XIP setup function" -- the name boot2 is historic and
|
||||
refers to its dual-purpose on RP2040, where it also handled vectoring
|
||||
from the bootrom into the user image.
|
||||
*/
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
*(.boot2)
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ <= 256,
|
||||
"ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
|
||||
|
||||
.rodata : {
|
||||
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* Vector table goes first in RAM, to avoid large alignment hole */
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.text : {
|
||||
__ram_text_start__ = .;
|
||||
*(.init)
|
||||
*(.text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
__ram_text_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
__ram_text_source__ = LOADADDR(.text);
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH =0xaa
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
|
||||
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
|
||||
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,302 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
/* The bootrom will enter the image at the point indicated in your
|
||||
IMAGE_DEF, which is usually the reset handler of your vector table.
|
||||
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol, and in our case is *different from the bootrom's entry point.*
|
||||
This is used to go back through the bootrom on debugger launches only,
|
||||
to perform the same initial flash setup that would be performed on a
|
||||
cold boot.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*libgcc.a:cmse_nonsecure_call.o
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
/* Note the boot2 section is optional, and should be discarded if there is
|
||||
no reference to it *inside* the binary, as it is not called by the
|
||||
bootrom. (The bootrom performs a simple best-effort XIP setup and
|
||||
leaves it to the binary to do anything more sophisticated.) However
|
||||
there is still a size limit of 256 bytes, to ensure the boot2 can be
|
||||
stored in boot RAM.
|
||||
|
||||
Really this is a "XIP setup function" -- the name boot2 is historic and
|
||||
refers to its dual-purpose on RP2040, where it also handled vectoring
|
||||
from the bootrom into the user image.
|
||||
*/
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
*(.boot2)
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ <= 256,
|
||||
"ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH =0xaa
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
|
||||
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
|
||||
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Note unlike RP2040, we start the image with a vector table even for
|
||||
NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the
|
||||
image by default; on RISC-V, the default is to enter the image at its
|
||||
lowest address, so an IMAGE_DEF item is required to specify the
|
||||
nondefault entry point. */
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
/* Vectors require 512-byte alignment on v8-M when >48 IRQs are used,
|
||||
so we would waste RAM if the vector table were not at the
|
||||
start. */
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
__reset_end = .;
|
||||
*(.time_critical*)
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.init)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
} > RAM
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > RAM
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > RAM
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > RAM
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
|
||||
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
|
||||
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
|
@ -18,6 +18,50 @@ generated_pico_flash_region(
|
|||
}),
|
||||
)
|
||||
|
||||
# It's possible to set linker scripts globally or on a per-binary basis.
|
||||
#
|
||||
# Setting globally:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your
|
||||
# desired linker script (eg @pico-sdk//src/pico_standard_link:no_flash_linker_script)
|
||||
#
|
||||
# Setting per-binary:
|
||||
# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib
|
||||
# * Manually add your desired linker script to each cc_binary.
|
||||
alias(
|
||||
name = "default_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:default_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:default_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "blocked_ram_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:blocked_ram_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "copy_to_ram_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:copy_to_ram_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:copy_to_ram_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "no_flash_linker_script",
|
||||
actual = select({
|
||||
"//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:no_flash_linker_script",
|
||||
"//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:no_flash_linker_script",
|
||||
"//conditions:default": "//bazel:incompatible_cc_lib",
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "pico_standard_link",
|
||||
target_compatible_with = compatible_with_rp2(),
|
||||
|
|
|
|||
|
|
@ -70,6 +70,36 @@ if (NOT TARGET pico_standard_link)
|
|||
set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT ${LDSCRIPT})
|
||||
endfunction()
|
||||
|
||||
# pico_set_linker_script_var(TARGET NAME VALUE)
|
||||
# \brief\ Set the linker script for the target
|
||||
#
|
||||
# \param\ NAME Name of variable to set
|
||||
# \param\ VALUE Value of variable to set
|
||||
function(pico_set_linker_script_var TARGET NAME VALUE)
|
||||
set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}")
|
||||
endfunction()
|
||||
|
||||
# pico_add_linker_script_override_path(TARGET PATH)
|
||||
# \brief\ Add an override linker script path to the target
|
||||
#
|
||||
# This can be used to override default linker script files with custom versions.
|
||||
#
|
||||
# For example, to use custom files in ${CMAKE_CURRENT_LIST_DIR}/extra_scripts instead of the default ones,
|
||||
# call pico_add_linker_script_override_path(TARGET ${CMAKE_CURRENT_LIST_DIR}/extra_scripts). This will
|
||||
# include the custom files first, overriding the default ones.
|
||||
#
|
||||
# Must be called before target_link_libraries, otherwise it will not override the default linker scripts.
|
||||
#
|
||||
# \param\ TARGET The target to add the linker script override path to
|
||||
# \param\ PATH The path containing the overriding linker scripts
|
||||
function(pico_add_linker_script_override_path TARGET PATH)
|
||||
get_target_property(OUT ${TARGET} LINK_LIBRARIES)
|
||||
if (OUT)
|
||||
message(WARNING "pico_add_linker_script_override_path does not work when called after target_link_libraries")
|
||||
endif()
|
||||
target_link_options(${TARGET} PRIVATE "LINKER:-L${PATH}")
|
||||
endfunction()
|
||||
|
||||
# pico_set_binary_type(TARGET TYPE)
|
||||
# \brief\ Set the binary type for the target
|
||||
#
|
||||
|
|
@ -124,9 +154,19 @@ if (NOT TARGET pico_standard_link)
|
|||
#math(EXPR PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}" OUTPUT_FORMAT HEXADECIMAL)
|
||||
set(PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}")
|
||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/pico_flash_region.template.ld ${CMAKE_BINARY_DIR}/pico_flash_region.ld)
|
||||
# add include path for linker scripts
|
||||
# add include path for linker scripts to find it
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}")
|
||||
|
||||
# add include path for main linker script sections
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/platform_scripts")
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/standard_scripts")
|
||||
|
||||
# add default locations script, so they can be referenced by pico_set_linker_script_var variables
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform_scripts/default_locations.ld")
|
||||
|
||||
# add variables set by pico_set_linker_script_var function
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:$<JOIN:$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT_VARS>,,>")
|
||||
|
||||
# LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld
|
||||
# if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld
|
||||
set(_LINKER_SCRIPT_EXPRESSION "$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>>,$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>,${PICO_LINKER_SCRIPT_PATH}/memmap_$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,>,${PICO_DEFAULT_BINARY_TYPE},$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>.ld>")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("//bazel:defs.bzl", "compatible_with_rp2")
|
||||
load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(
|
||||
[
|
||||
"memory_aliases_default.ld",
|
||||
"memory_aliases_no_flash.ld",
|
||||
"memory_flash.ld",
|
||||
"memory_ram.ld",
|
||||
"memory_scratch.ld",
|
||||
"memory_xip_ram.ld",
|
||||
"section_copy_to_ram_data.ld",
|
||||
"section_copy_to_ram_text.ld",
|
||||
"section_default_data.ld",
|
||||
"section_default_text.ld",
|
||||
"section_end.ld",
|
||||
"section_flash_end.ld",
|
||||
"section_heap.ld",
|
||||
"section_no_flash_data.ld",
|
||||
"section_no_flash_text.ld",
|
||||
"sections_copy_to_ram.ld",
|
||||
"section_scratch.ld",
|
||||
"sections_default.ld",
|
||||
"sections_no_flash.ld",
|
||||
"set_memory_locations.ld",
|
||||
"memmap_default.ld",
|
||||
"memmap_no_flash.ld",
|
||||
"memmap_copy_to_ram.ld",
|
||||
]
|
||||
)
|
||||
|
||||
include_linker_script_dir(
|
||||
name = "rp2_linker_script_args",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "rp2_linker_scripts",
|
||||
target_compatible_with = compatible_with_rp2(),
|
||||
deps = [
|
||||
"rp2_linker_script_args",
|
||||
"memory_aliases_default.ld",
|
||||
"memory_aliases_no_flash.ld",
|
||||
"memory_flash.ld",
|
||||
"memory_ram.ld",
|
||||
"memory_scratch.ld",
|
||||
"memory_xip_ram.ld",
|
||||
"section_copy_to_ram_data.ld",
|
||||
"section_copy_to_ram_text.ld",
|
||||
"section_default_data.ld",
|
||||
"section_default_text.ld",
|
||||
"section_end.ld",
|
||||
"section_flash_end.ld",
|
||||
"section_heap.ld",
|
||||
"section_no_flash_data.ld",
|
||||
"section_no_flash_text.ld",
|
||||
"sections_copy_to_ram.ld",
|
||||
"section_scratch.ld",
|
||||
"sections_default.ld",
|
||||
"sections_no_flash.ld",
|
||||
"set_memory_locations.ld",
|
||||
"memmap_default.ld",
|
||||
"memmap_no_flash.ld",
|
||||
"memmap_copy_to_ram.ld",
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* Include platform memory locations */
|
||||
INCLUDE "set_memory_locations.ld"
|
||||
|
||||
/* Include memory regions used */
|
||||
INCLUDE "memory_flash.ld"
|
||||
INCLUDE "memory_ram.ld"
|
||||
INCLUDE "memory_scratch.ld"
|
||||
|
||||
/* Include aliases for storage memory regions */
|
||||
INCLUDE "memory_aliases_default.ld"
|
||||
|
||||
/* Define entry point symbol */
|
||||
ENTRY(_entry_point)
|
||||
|
||||
/* Include default sections */
|
||||
INCLUDE "sections_copy_to_ram.ld"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* Include platform memory locations */
|
||||
INCLUDE "set_memory_locations.ld"
|
||||
|
||||
/* Include memory regions used */
|
||||
INCLUDE "memory_flash.ld"
|
||||
INCLUDE "memory_ram.ld"
|
||||
INCLUDE "memory_scratch.ld"
|
||||
|
||||
/* Include aliases for storage memory regions */
|
||||
INCLUDE "memory_aliases_default.ld"
|
||||
|
||||
/* Define entry point symbol */
|
||||
ENTRY(_entry_point)
|
||||
|
||||
/* Include default sections */
|
||||
INCLUDE "sections_default.ld"
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/* Include platform memory locations */
|
||||
INCLUDE "set_memory_locations.ld"
|
||||
|
||||
/* Include memory regions used */
|
||||
INCLUDE "memory_ram.ld"
|
||||
INCLUDE "memory_scratch.ld"
|
||||
|
||||
/* Include aliases for no_flash storage memory regions (alias to themselves) */
|
||||
INCLUDE "memory_aliases_no_flash.ld"
|
||||
|
||||
/* Define entry point symbol */
|
||||
ENTRY(_entry_point)
|
||||
|
||||
/* Include no_flash sections */
|
||||
INCLUDE "sections_no_flash.ld"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
REGION_ALIAS("RAM_STORE", FLASH);
|
||||
REGION_ALIAS("SCRATCH_X_STORE", FLASH);
|
||||
REGION_ALIAS("SCRATCH_Y_STORE", FLASH);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
REGION_ALIAS("RAM_STORE", RAM);
|
||||
REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X);
|
||||
REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y);
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
MEMORY
|
||||
{
|
||||
INCLUDE "pico_flash_region.ld"
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
MEMORY
|
||||
{
|
||||
RAM(rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
MEMORY
|
||||
{
|
||||
SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_ORIGIN, LENGTH = SCRATCH_X_LENGTH
|
||||
SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_ORIGIN, LENGTH = SCRATCH_Y_LENGTH
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
MEMORY
|
||||
{
|
||||
XIP_RAM(rwx) : ORIGIN = XIP_RAM_ORIGIN, LENGTH = XIP_RAM_LENGTH
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
SECTIONS
|
||||
{
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* On Arm, the bootrom expects a VT at the start of the
|
||||
image by default; on RISC-V, the default is to enter the image at its
|
||||
lowest address, so an IMAGE_DEF item is required to specify the
|
||||
nondefault entry point. */
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
/* The bootrom will enter the image at the point indicated in your
|
||||
IMAGE_DEF, which is usually the reset handler of your vector table.
|
||||
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol, and in our case is *different from the bootrom's entry point.*
|
||||
This is used to go back through the bootrom on debugger launches only,
|
||||
to perform the same initial flash setup that would be performed on a
|
||||
cold boot.
|
||||
*/
|
||||
|
||||
.flashtext : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
/* Note the boot2 section is optional, and should be discarded if there is
|
||||
no reference to it *inside* the binary, as it is not called by the
|
||||
bootrom. (The bootrom performs a simple best-effort XIP setup and
|
||||
leaves it to the binary to do anything more sophisticated.) However
|
||||
there is still a size limit of 256 bytes, to ensure the boot2 can be
|
||||
stored in boot RAM.
|
||||
|
||||
Really this is a "XIP setup function" -- the name boot2 is historic and
|
||||
refers to its dual-purpose on RP2040, where it also handled vectoring
|
||||
from the bootrom into the user image.
|
||||
*/
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
*(.boot2)
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ <= 256,
|
||||
"ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
|
||||
|
||||
.rodata : {
|
||||
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* Vector table goes first in RAM, to avoid large alignment hole */
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.text : {
|
||||
__ram_text_start__ = .;
|
||||
*(.init)
|
||||
*(.text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
__ram_text_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
__ram_text_source__ = LOADADDR(.text);
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
SECTIONS
|
||||
{
|
||||
.ram_vector_table (NOLOAD): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM AT> FLASH
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
SECTIONS
|
||||
{
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
/* The bootrom will enter the image at the point indicated in your
|
||||
IMAGE_DEF, which is usually the reset handler of your vector table.
|
||||
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol, and in our case is *different from the bootrom's entry point.*
|
||||
This is used to go back through the bootrom on debugger launches only,
|
||||
to perform the same initial flash setup that would be performed on a
|
||||
cold boot.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*libgcc.a:cmse_nonsecure_call.o
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
/* Note the boot2 section is optional, and should be discarded if there is
|
||||
no reference to it *inside* the binary, as it is not called by the
|
||||
bootrom. (The bootrom performs a simple best-effort XIP setup and
|
||||
leaves it to the binary to do anything more sophisticated.) However
|
||||
there is still a size limit of 256 bytes, to ensure the boot2 can be
|
||||
stored in boot RAM.
|
||||
|
||||
Really this is a "XIP setup function" -- the name boot2 is historic and
|
||||
refers to its dual-purpose on RP2040, where it also handled vectoring
|
||||
from the bootrom into the user image.
|
||||
*/
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
*(.boot2)
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ <= 256,
|
||||
"ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* picolibc and LLVM */
|
||||
PROVIDE (__heap_start = __end__);
|
||||
PROVIDE (__heap_end = __HeapLimit);
|
||||
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
|
||||
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
|
||||
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
|
||||
|
||||
/* llvm-libc */
|
||||
PROVIDE (_end = __end__);
|
||||
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
SECTIONS
|
||||
{
|
||||
.flash_end : {
|
||||
KEEP(*(.embedded_end_block*))
|
||||
PROVIDE(__flash_binary_end = .);
|
||||
} > FLASH =0xaa
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
SECTIONS
|
||||
{
|
||||
.heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
} > RAM
|
||||
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
|
||||
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
|
||||
__HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM);
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
SECTIONS
|
||||
{
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
/* All data end */
|
||||
__tdata_end = .;
|
||||
} > RAM
|
||||
PROVIDE(__data_end__ = .);
|
||||
|
||||
.uninitialized_data (NOLOAD): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.tbss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
__tls_base = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
|
||||
__tls_end = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
__tbss_end = .;
|
||||
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
PROVIDE(__global_pointer$ = . + 2K);
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* Note unlike RP2040, we start the image with a vector table even for
|
||||
NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the
|
||||
image by default; on RISC-V, the default is to enter the image at its
|
||||
lowest address, so an IMAGE_DEF item is required to specify the
|
||||
nondefault entry point. */
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
/* Vectors require 512-byte alignment on v8-M when >48 IRQs are used,
|
||||
so we would waste RAM if the vector table were not at the
|
||||
start. */
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.embedded_block))
|
||||
__embedded_block_end = .;
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
__reset_end = .;
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.init)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
} > RAM
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
*(.srodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > RAM
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > RAM
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > RAM
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
SECTIONS
|
||||
{
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT> SCRATCH_X_STORE
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT> SCRATCH_Y_STORE
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (NOLOAD):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > SCRATCH_Y
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
INCLUDE "section_copy_to_ram_text.ld"
|
||||
INCLUDE "section_copy_to_ram_data.ld"
|
||||
INCLUDE "section_heap.ld"
|
||||
INCLUDE "section_scratch.ld"
|
||||
INCLUDE "section_flash_end.ld"
|
||||
INCLUDE "section_end.ld"
|
||||
INCLUDE "section_platform_end.ld"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
INCLUDE "section_default_text.ld"
|
||||
INCLUDE "section_default_data.ld"
|
||||
INCLUDE "section_heap.ld"
|
||||
INCLUDE "section_scratch.ld"
|
||||
INCLUDE "section_flash_end.ld"
|
||||
INCLUDE "section_end.ld"
|
||||
INCLUDE "section_platform_end.ld"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
INCLUDE "section_no_flash_text.ld"
|
||||
INCLUDE "section_no_flash_data.ld"
|
||||
INCLUDE "section_heap.ld"
|
||||
INCLUDE "section_scratch.ld"
|
||||
INCLUDE "section_end.ld"
|
||||
INCLUDE "section_platform_end.ld"
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : RAM_ORIGIN_DEFAULT;
|
||||
RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : RAM_LENGTH_DEFAULT;
|
||||
SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : SCRATCH_X_ORIGIN_DEFAULT;
|
||||
SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : SCRATCH_X_LENGTH_DEFAULT;
|
||||
SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : SCRATCH_Y_ORIGIN_DEFAULT;
|
||||
SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : SCRATCH_Y_LENGTH_DEFAULT;
|
||||
XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : XIP_RAM_ORIGIN_DEFAULT;
|
||||
XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : XIP_RAM_LENGTH_DEFAULT;
|
||||
|
|
@ -214,6 +214,30 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS)
|
|||
pico_add_extra_outputs(kitchen_sink_blocked_ram)
|
||||
target_compile_definitions(kitchen_sink_blocked_ram PRIVATE KITCHEN_SINK_ID="blocked-ram binary")
|
||||
endif()
|
||||
|
||||
add_executable(kitchen_sink_ram_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
|
||||
# Have ram start from 0x20020000 length 128k, and heap start from 0x20030000
|
||||
pico_set_linker_script_var(kitchen_sink_ram_custom RAM_ORIGIN 0x20020000)
|
||||
pico_set_linker_script_var(kitchen_sink_ram_custom RAM_LENGTH 128k)
|
||||
pico_set_linker_script_var(kitchen_sink_ram_custom HEAP_LOC 0x20030000)
|
||||
target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options)
|
||||
pico_add_extra_outputs(kitchen_sink_ram_custom)
|
||||
target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary")
|
||||
|
||||
add_executable(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
|
||||
pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_ram_section_scripts)
|
||||
target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options)
|
||||
pico_add_extra_outputs(kitchen_sink_ram_section)
|
||||
target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1)
|
||||
|
||||
if (NOT PICO_C_COMPILER_IS_CLANG)
|
||||
# Clang does not support overlay sections
|
||||
add_executable(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
|
||||
pico_add_linker_script_override_path(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts)
|
||||
target_link_libraries(kitchen_sink_simple_overlay kitchen_sink_libs kitchen_sink_options)
|
||||
pico_add_extra_outputs(kitchen_sink_simple_overlay)
|
||||
target_compile_definitions(kitchen_sink_simple_overlay PRIVATE KITCHEN_SINK_ID="simple overlay binary" EXTRA_DATA_SECTION=2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,42 @@ int main(void) {
|
|||
hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL));
|
||||
hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL));
|
||||
printf("%f\n", foox(1.3f, 2.6f));
|
||||
#ifdef EXTRA_DATA_SECTION
|
||||
#if EXTRA_DATA_SECTION > 1
|
||||
extern uint32_t __overlays_start__;
|
||||
uint32_t stored_words;
|
||||
|
||||
static int overlay_first __attribute__((section(".overlay_first"))) = 12345678;
|
||||
printf("overlay_first before load = %d\n", overlay_first);
|
||||
static int overlay_second_one __attribute__((section(".overlay_second"))) = 34567890;
|
||||
static int overlay_second_two __attribute__((section(".overlay_second"))) = 56789012;
|
||||
printf("overlay_second before load = %d, %d\n", overlay_second_one, overlay_second_two);
|
||||
|
||||
extern uint32_t __load_start_overlay_second;
|
||||
extern uint32_t __load_stop_overlay_second;
|
||||
stored_words = (uint32_t)(&__load_stop_overlay_second - &__load_start_overlay_second);
|
||||
memcpy(&__overlays_start__, &__load_start_overlay_second, 4 * stored_words);
|
||||
printf("overlay_second after load = %d, %d\n", overlay_second_one, overlay_second_two);
|
||||
|
||||
extern uint32_t __load_start_overlay_first;
|
||||
extern uint32_t __load_stop_overlay_first;
|
||||
stored_words = (uint32_t)(&__load_stop_overlay_first - &__load_start_overlay_first);
|
||||
memcpy(&__overlays_start__, &__load_start_overlay_first, 4 * stored_words);
|
||||
printf("overlay_first after load = %d\n", overlay_first);
|
||||
printf("overlay_second after overlay_first load = %d, %d\n", overlay_second_one, overlay_second_two);
|
||||
#else
|
||||
static int extra_data __attribute__((section(".extra_data"))) = 12345678;
|
||||
printf("extra_data before load = %d\n", extra_data);
|
||||
|
||||
extern uint32_t __extra_data_source__;
|
||||
extern uint32_t __extra_data_start__;
|
||||
extern uint32_t __extra_data_end__;
|
||||
uint32_t stored_words = (uint32_t)(&__extra_data_end__ - &__extra_data_start__);
|
||||
memcpy(&__extra_data_start__, &__extra_data_source__, 4 * stored_words);
|
||||
|
||||
printf("extra_data after load = %d\n", extra_data);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef __riscv
|
||||
// this should compile as we are Cortex M0+
|
||||
pico_default_asm ("SVC #3");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
INCLUDE "section_default_text.ld"
|
||||
INCLUDE "section_default_data.ld"
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.extra_data : {
|
||||
__extra_data_start__ = .;
|
||||
*(.extra_data*)
|
||||
. = ALIGN(4);
|
||||
__extra_data_end__ = .;
|
||||
} > RAM AT> RAM_STORE
|
||||
__extra_data_source__ = LOADADDR(.extra_data);
|
||||
}
|
||||
|
||||
INCLUDE "section_heap.ld"
|
||||
INCLUDE "section_scratch.ld"
|
||||
INCLUDE "section_flash_end.ld"
|
||||
INCLUDE "section_end.ld"
|
||||
INCLUDE "section_platform_end.ld"
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
INCLUDE "section_default_text.ld"
|
||||
INCLUDE "section_default_data.ld"
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__overlays_start__ = .);
|
||||
OVERLAY : {
|
||||
.overlay_first {
|
||||
KEEP (*(.first*))
|
||||
. = ALIGN(4);
|
||||
}
|
||||
.overlay_second {
|
||||
KEEP (*(.second*))
|
||||
. = ALIGN(4);
|
||||
}
|
||||
} > RAM AT> RAM_STORE
|
||||
PROVIDE(__overlays_end__ = .);
|
||||
}
|
||||
|
||||
INCLUDE "section_heap.ld"
|
||||
INCLUDE "section_scratch.ld"
|
||||
INCLUDE "section_flash_end.ld"
|
||||
INCLUDE "section_end.ld"
|
||||
INCLUDE "section_platform_end.ld"
|
||||
Loading…
Add table
Reference in a new issue