This commit is contained in:
will-v-pi 2026-03-12 14:24:18 +00:00 committed by GitHub
commit 4e0795a151
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
62 changed files with 1568 additions and 2051 deletions

View file

@ -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

View 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"],
)

View file

@ -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)

View file

@ -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",
],
)

View 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()

View file

@ -0,0 +1,4 @@
/* Use blocked ram */
RAM_ORIGIN = 0x21000000;
INCLUDE "memmap_default.ld"

View file

@ -0,0 +1 @@
INCLUDE "memmap_copy_to_ram.ld"

View file

@ -0,0 +1 @@
INCLUDE "memmap_default.ld"

View file

@ -0,0 +1 @@
INCLUDE "memmap_no_flash.ld"

View 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",
],
)

View file

@ -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;

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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 */
}

View file

@ -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",
],
)

View 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()

View file

@ -0,0 +1 @@
INCLUDE "memmap_copy_to_ram.ld"

View file

@ -0,0 +1 @@
INCLUDE "memmap_default.ld"

View file

@ -0,0 +1 @@
INCLUDE "memmap_no_flash.ld"

View 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",
],
)

View file

@ -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;

View file

@ -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 */
}

View file

@ -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(

View file

@ -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()

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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(),

View file

@ -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>")

View file

@ -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",
],
)

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -0,0 +1,3 @@
REGION_ALIAS("RAM_STORE", FLASH);
REGION_ALIAS("SCRATCH_X_STORE", FLASH);
REGION_ALIAS("SCRATCH_Y_STORE", FLASH);

View file

@ -0,0 +1,3 @@
REGION_ALIAS("RAM_STORE", RAM);
REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X);
REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y);

View file

@ -0,0 +1,4 @@
MEMORY
{
INCLUDE "pico_flash_region.ld"
}

View file

@ -0,0 +1,4 @@
MEMORY
{
RAM(rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH
}

View file

@ -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
}

View file

@ -0,0 +1,4 @@
MEMORY
{
XIP_RAM(rwx) : ORIGIN = XIP_RAM_ORIGIN, LENGTH = XIP_RAM_LENGTH
}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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 */
}

View file

@ -0,0 +1,7 @@
SECTIONS
{
.flash_end : {
KEEP(*(.embedded_end_block*))
PROVIDE(__flash_binary_end = .);
} > FLASH =0xaa
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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;

View file

@ -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)

View file

@ -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");

View file

@ -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"

View file

@ -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"