Initial Release
This commit is contained in:
93
src/rp2_common/pico_standard_link/CMakeLists.txt
Normal file
93
src/rp2_common/pico_standard_link/CMakeLists.txt
Normal file
@ -0,0 +1,93 @@
|
||||
if (NOT TARGET pico_standard_link)
|
||||
add_library(pico_standard_link INTERFACE)
|
||||
|
||||
target_sources(pico_standard_link INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/crt0.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/new_delete.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/binary_info.c
|
||||
)
|
||||
|
||||
pico_add_map_output(pico_standard_link)
|
||||
|
||||
# todo revisit when we do Clang
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib")
|
||||
endif ()
|
||||
|
||||
target_link_libraries(pico_standard_link INTERFACE hardware_regs pico_bootrom pico_binary_info pico_cxx_options)
|
||||
|
||||
function(pico_add_link_depend TARGET dependency)
|
||||
get_target_property(target_type ${TARGET} TYPE)
|
||||
if (${target_type} STREQUAL "INTERFACE_LIBRARY")
|
||||
set(PROP "INTERFACE_LINK_DEPENDS")
|
||||
else()
|
||||
set(PROP "LINK_DEPENDS")
|
||||
endif()
|
||||
get_target_property(_LINK_DEPENDS ${TARGET} ${PROP})
|
||||
if (NOT _LINK_DEPENDS)
|
||||
set(_LINK_DEPENDS ${dependency})
|
||||
else()
|
||||
list(APPEND _LINK_DEPENDS ${dependency})
|
||||
endif()
|
||||
set_target_properties(${TARGET} PROPERTIES ${PROP} "${_LINK_DEPENDS}")
|
||||
endfunction()
|
||||
|
||||
# need this because cmake does not appear to have a way to override an INTERFACE variable
|
||||
function(pico_set_linker_script TARGET LDSCRIPT)
|
||||
set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT ${LDSCRIPT})
|
||||
pico_add_link_depend(${TARGET} ${LDSCRIPT})
|
||||
endfunction()
|
||||
|
||||
function(pico_set_binary_type TARGET TYPE)
|
||||
set_target_properties(${TARGET} PROPERTIES PICO_TARGET_BINARY_TYPE ${TYPE})
|
||||
endfunction()
|
||||
|
||||
if (PICO_NO_FLASH)
|
||||
set(PICO_DEFAULT_BINARY_TYPE no_flash)
|
||||
elseif (PICO_USE_BLOCKED_RAM)
|
||||
set(PICO_DEFAULT_BINARY_TYPE blocked_ram)
|
||||
elseif (PICO_COPY_TO_RAM)
|
||||
set(PICO_DEFAULT_BINARY_TYPE copy_to_ram)
|
||||
else()
|
||||
set(PICO_DEFAULT_BINARY_TYPE default)
|
||||
endif()
|
||||
|
||||
# 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
|
||||
target_link_options(pico_standard_link INTERFACE
|
||||
"LINKER:--script=$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>>,$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>,${CMAKE_CURRENT_LIST_DIR}/memmap_$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,>,${PICO_DEFAULT_BINARY_TYPE},$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>.ld>"
|
||||
)
|
||||
|
||||
# PICO_NO_FLASH will be set based on PICO_TARGET_BUILD_TYPE target property being equal to no_flash if set, otherwise to the value of the PICO_NO_FLASH cmake variable unless PICO_TARGET_TYPE is set to something else
|
||||
# PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
|
||||
target_compile_definitions(pico_standard_link INTERFACE PICO_NO_FLASH=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
|
||||
# PICO_USE_BLOCKED_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to use_blocked_ram if set, otherwise to the value of the PICO_USE_BLOCKED_RAM cmake variable unless PICO_TARGET_TYPE is set to something else
|
||||
# PICO_BUILD_DEFINE: PICO_USE_BLOCKS_RAM, whether this is a 'blocked_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
|
||||
target_compile_definitions(pico_standard_link INTERFACE PICO_USE_BLOCKED_RAM=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,use_blocked_ram>,1,$<AND:$<BOOL:${PICO_USE_BLOCKED_RAM}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
|
||||
# PICO_COPY_TO_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to copy_to_ram if set, otherwise to the value of the PICO_COPY_TO_RAM cmake variable unless PICO_TARGET_TYPE is set to something else
|
||||
# PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
|
||||
target_compile_definitions(pico_standard_link INTERFACE PICO_COPY_TO_RAM=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,copy_to_ram>,1,$<AND:$<BOOL:${PICO_COPY_TO_RAM}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
|
||||
|
||||
target_compile_definitions(pico_standard_link INTERFACE PICO_CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}")
|
||||
if (PICO_DEOPTIMIZED_DEBUG AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
target_compile_definitions(pico_standard_link INTERFACE PICO_DEOPTIMIZED_DEBUG=1)
|
||||
endif()
|
||||
|
||||
# todo revisit/recall reasoning for why not -nostartfiles always?
|
||||
# -nostartfiles will be added if PICO_NO_FLASH would be defined to 1
|
||||
target_link_options(pico_standard_link INTERFACE $<$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>:-nostartfiles>)
|
||||
# boot_stage2 will be linked if PICO_NO_FLASH would be defined to 0
|
||||
target_link_libraries(pico_standard_link INTERFACE $<$<NOT:$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>>:$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>>,$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>,bs2_default>_library>)
|
||||
|
||||
# done in compiler now
|
||||
#target_link_options(pico_standard_link INTERFACE "LINKER:--build-id=none")
|
||||
|
||||
# this line occasionally useful for debugging ... todo maybe make a PICO_ var
|
||||
# target_compile_options(pico_standard_link INTERFACE --save-temps) #debugging only
|
||||
|
||||
# PICO_CMAKE_CONFIG: PICO_NO_GC_SECTIONS, Disable -ffunction-sections -fdata-sections, and --gc-sections, type=bool, default=0, advanced=true, group=pico_standard_link
|
||||
if (NOT PICO_NO_GC_SECTIONS)
|
||||
target_compile_options(pico_standard_link INTERFACE -ffunction-sections -fdata-sections)
|
||||
target_link_options(pico_standard_link INTERFACE "LINKER:--gc-sections")
|
||||
endif()
|
||||
endif()
|
85
src/rp2_common/pico_standard_link/binary_info.c
Normal file
85
src/rp2_common/pico_standard_link/binary_info.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#if !PICO_NO_BINARY_INFO && !PICO_NO_PROGRAM_INFO
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
// Note we put at most 4 pieces of binary info in the reset section because that's how much spare space we had
|
||||
// (picked the most common ones)... if there is a link failure because of .reset section overflow then move
|
||||
// more out.
|
||||
#define reset_section_attr __attribute__((section(".reset")))
|
||||
|
||||
#if !PICO_NO_FLASH
|
||||
#ifndef PICO_NO_BI_BINARY_SIZE
|
||||
extern char __flash_binary_end;
|
||||
bi_decl_with_attr(bi_binary_end((uintptr_t)&__flash_binary_end), reset_section_attr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_PROGRAM_BUILD_DATE
|
||||
#ifndef PICO_PROGRAM_BUILD_DATE
|
||||
#define PICO_PROGRAM_BUILD_DATE __DATE__
|
||||
#endif
|
||||
bi_decl_with_attr(bi_program_build_date_string(PICO_PROGRAM_BUILD_DATE), reset_section_attr);
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_PROGRAM_NAME
|
||||
#if !defined(PICO_PROGRAM_NAME) && defined(PICO_TARGET_NAME)
|
||||
#define PICO_PROGRAM_NAME PICO_TARGET_NAME
|
||||
#endif
|
||||
#ifdef PICO_PROGRAM_NAME
|
||||
bi_decl_with_attr(bi_program_name(PICO_PROGRAM_NAME), reset_section_attr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_PICO_BOARD
|
||||
#ifdef PICO_BOARD
|
||||
bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PICO_BOARD, PICO_BOARD))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_SDK_VERSION
|
||||
#ifdef PICO_SDK_VERSION_STRING
|
||||
bi_decl_with_attr(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_SDK_VERSION, PICO_SDK_VERSION_STRING),reset_section_attr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_PROGRAM_VERSION_STRING
|
||||
#ifdef PICO_PROGRAM_VERSION_STRING
|
||||
bi_decl(bi_program_version_string(PICO_PROGRAM_VERSION_STRING))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !PICO_NO_BI_PROGRAM_DESCRIPTION
|
||||
#ifdef PICO_PROGRAM_DESCRIPTION
|
||||
bi_decl(bi_program_description(PICO_PROGRAM_DESCRIPTION))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BI_PROGRAM_URL
|
||||
#ifdef PICO_PROGRAM_URL
|
||||
bi_decl(bi_program_url(PICO_PROGRAM_URL))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PICO_NO_BUILD_TYPE_FEATURE
|
||||
#ifdef PICO_CMAKE_BUILD_TYPE
|
||||
bi_decl(bi_program_build_attribute(PICO_CMAKE_BUILD_TYPE))
|
||||
#else
|
||||
#ifndef NDEBUG
|
||||
bi_decl(bi_program_build_attribute("Debug"))
|
||||
#else
|
||||
bi_decl(bi_program_build_attribute("Release"))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PICO_DEOPTIMIZED_DEBUG
|
||||
bi_decl(bi_program_build_attribute("All optimization disabled"))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
315
src/rp2_common/pico_standard_link/crt0.S
Normal file
315
src/rp2_common/pico_standard_link/crt0.S
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "hardware/regs/m0plus.h"
|
||||
#include "hardware/platform_defs.h"
|
||||
#include "hardware/regs/addressmap.h"
|
||||
#include "hardware/regs/sio.h"
|
||||
#include "pico/binary_info/defs.h"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#ifndef COLLAPSE_IRQS
|
||||
#define COLLAPSE_IRQS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .vectors, "ax"
|
||||
.align 2
|
||||
|
||||
.global __vectors
|
||||
__vectors:
|
||||
.word __StackTop
|
||||
.word _reset_handler
|
||||
.word isr_nmi
|
||||
.word isr_hardfault
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_svcall
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_invalid // Reserved, should never fire
|
||||
.word isr_pendsv
|
||||
.word isr_systick
|
||||
.word isr_irq0
|
||||
.word isr_irq1
|
||||
.word isr_irq2
|
||||
.word isr_irq3
|
||||
.word isr_irq4
|
||||
.word isr_irq5
|
||||
.word isr_irq6
|
||||
.word isr_irq7
|
||||
.word isr_irq8
|
||||
.word isr_irq9
|
||||
.word isr_irq10
|
||||
.word isr_irq11
|
||||
.word isr_irq12
|
||||
.word isr_irq13
|
||||
.word isr_irq14
|
||||
.word isr_irq15
|
||||
.word isr_irq16
|
||||
.word isr_irq17
|
||||
.word isr_irq18
|
||||
.word isr_irq19
|
||||
.word isr_irq20
|
||||
.word isr_irq21
|
||||
.word isr_irq22
|
||||
.word isr_irq23
|
||||
.word isr_irq24
|
||||
.word isr_irq25
|
||||
.word isr_irq26
|
||||
.word isr_irq27
|
||||
.word isr_irq28
|
||||
.word isr_irq29
|
||||
.word isr_irq30
|
||||
.word isr_irq31
|
||||
|
||||
// Declare a weak symbol for each ISR.
|
||||
// By default, they will fall through to the undefined IRQ handler below (breakpoint),
|
||||
// but can be overridden by C functions with correct name.
|
||||
|
||||
.macro decl_isr_bkpt name
|
||||
.weak \name
|
||||
.type \name,%function
|
||||
.thumb_func
|
||||
\name:
|
||||
bkpt #0
|
||||
.endm
|
||||
|
||||
// these are separated out for clarity
|
||||
decl_isr_bkpt isr_invalid
|
||||
decl_isr_bkpt isr_nmi
|
||||
decl_isr_bkpt isr_hardfault
|
||||
decl_isr_bkpt isr_svcall
|
||||
decl_isr_bkpt isr_pendsv
|
||||
decl_isr_bkpt isr_systick
|
||||
|
||||
.macro decl_isr name
|
||||
.weak \name
|
||||
.type \name,%function
|
||||
.thumb_func
|
||||
\name:
|
||||
.endm
|
||||
|
||||
decl_isr isr_irq0
|
||||
decl_isr isr_irq1
|
||||
decl_isr isr_irq2
|
||||
decl_isr isr_irq3
|
||||
decl_isr isr_irq4
|
||||
decl_isr isr_irq5
|
||||
decl_isr isr_irq6
|
||||
decl_isr isr_irq7
|
||||
decl_isr isr_irq8
|
||||
decl_isr isr_irq9
|
||||
decl_isr isr_irq10
|
||||
decl_isr isr_irq11
|
||||
decl_isr isr_irq12
|
||||
decl_isr isr_irq13
|
||||
decl_isr isr_irq14
|
||||
decl_isr isr_irq15
|
||||
decl_isr isr_irq16
|
||||
decl_isr isr_irq17
|
||||
decl_isr isr_irq18
|
||||
decl_isr isr_irq19
|
||||
decl_isr isr_irq20
|
||||
decl_isr isr_irq21
|
||||
decl_isr isr_irq22
|
||||
decl_isr isr_irq23
|
||||
decl_isr isr_irq24
|
||||
decl_isr isr_irq25
|
||||
decl_isr isr_irq26
|
||||
decl_isr isr_irq27
|
||||
decl_isr isr_irq28
|
||||
decl_isr isr_irq29
|
||||
decl_isr isr_irq30
|
||||
decl_isr isr_irq31
|
||||
|
||||
// All unhandled USER IRQs fall through to here
|
||||
.global __unhandled_user_irq
|
||||
.thumb_func
|
||||
__unhandled_user_irq:
|
||||
bl __get_current_exception
|
||||
subs r0, #16
|
||||
.global unhandled_user_irq_num_in_r0
|
||||
unhandled_user_irq_num_in_r0:
|
||||
bkpt #0
|
||||
|
||||
.section .reset, "ax"
|
||||
|
||||
// This is the beginning of the image, which is entered from stage2 or bootrom USB MSD watchdog reboot
|
||||
|
||||
// note if we are NO_FLASH then start: below is currently identical anyway, so save 4 bytes
|
||||
#if !PICO_NO_FLASH
|
||||
// We simply install our own vector table and redirect through it
|
||||
ldr r0, =__vectors
|
||||
b __vector_entry
|
||||
#endif
|
||||
|
||||
// ELF entry point generally called when we load an ELF via debugger
|
||||
.type _entry_point,%function
|
||||
.thumb_func
|
||||
.global _entry_point
|
||||
_entry_point:
|
||||
|
||||
#if PICO_NO_FLASH
|
||||
// non flash
|
||||
ldr r0, =__vectors
|
||||
#else
|
||||
// todo clear watchdog?
|
||||
// When using flash, we install and use the ROM vector table to go thru regular bootrom/stage2 flash sequence
|
||||
movs r0, #0
|
||||
#endif
|
||||
|
||||
__vector_entry:
|
||||
ldr r1, =(PPB_BASE + M0PLUS_CPUID_OFFSET)
|
||||
str r0, [r1, #8]
|
||||
ldmia r0!, {r1, r2}
|
||||
msr msp, r1
|
||||
bx r2
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Reset handler:
|
||||
// - initialises .data
|
||||
// - clears .bss
|
||||
// - calls runtime_init
|
||||
// - calls main
|
||||
// - calls exit (which should eventually hang the processor via _exit)
|
||||
|
||||
.type _reset_handler,%function
|
||||
.thumb_func
|
||||
_reset_handler:
|
||||
// Hang all cores except core 0
|
||||
ldr r0, =(SIO_BASE + SIO_CPUID_OFFSET)
|
||||
ldr r0, [r0]
|
||||
cmp r0, #0
|
||||
bne wait_for_vector
|
||||
|
||||
adr r4, data_cpy_table
|
||||
|
||||
// assume there is at least one entry
|
||||
1:
|
||||
ldmia r4!, {r1-r3}
|
||||
cmp r1, #0
|
||||
beq 2f
|
||||
bl data_cpy
|
||||
b 1b
|
||||
2:
|
||||
|
||||
// Zero out the BSS
|
||||
ldr r1, =__bss_start__
|
||||
ldr r2, =__bss_end__
|
||||
movs r0, #0
|
||||
b bss_fill_test
|
||||
bss_fill_loop:
|
||||
stm r1!, {r0}
|
||||
bss_fill_test:
|
||||
cmp r1, r2
|
||||
bne bss_fill_loop
|
||||
|
||||
platform_entry: // symbol for stack traces
|
||||
// Use 32-bit jumps, in case these symbols are moved out of branch range
|
||||
// (e.g. if main is in SRAM and crt0 in flash)
|
||||
ldr r1, =runtime_init
|
||||
blx r1
|
||||
ldr r1, =main
|
||||
blx r1
|
||||
ldr r1, =exit
|
||||
blx r1
|
||||
// exit should not return. If it does, hang the core.
|
||||
// (fall thru into our hang _exit impl
|
||||
.weak _exit
|
||||
.type _exit,%function
|
||||
.thumb_func
|
||||
_exit:
|
||||
1: // separate label because _exit can be moved out of branch range
|
||||
bkpt #0
|
||||
b 1b
|
||||
|
||||
data_cpy_loop:
|
||||
ldm r1!, {r0}
|
||||
stm r2!, {r0}
|
||||
data_cpy:
|
||||
cmp r2, r3
|
||||
blo data_cpy_loop
|
||||
bx lr
|
||||
|
||||
#if !PICO_NO_BINARY_INFO
|
||||
binary_info_header:
|
||||
.word BINARY_INFO_MARKER_START
|
||||
.word __binary_info_start
|
||||
.word __binary_info_end
|
||||
.word data_cpy_table // we may need to decode pointers that are in RAM at runtime.
|
||||
.word BINARY_INFO_MARKER_END
|
||||
#endif
|
||||
|
||||
.align 2
|
||||
data_cpy_table:
|
||||
#if PICO_COPY_TO_RAM
|
||||
.word __ram_text_source__
|
||||
.word __ram_text_start__
|
||||
.word __ram_text_end__
|
||||
#endif
|
||||
.word __etext
|
||||
.word __data_start__
|
||||
.word __data_end__
|
||||
|
||||
.word __scratch_x_source__
|
||||
.word __scratch_x_start__
|
||||
.word __scratch_x_end__
|
||||
|
||||
.word __scratch_y_source__
|
||||
.word __scratch_y_start__
|
||||
.word __scratch_y_end__
|
||||
|
||||
.word 0 // null terminator
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Provide safe defaults for _exit and runtime_init
|
||||
// Full implementations usually provided by platform.c
|
||||
|
||||
.weak runtime_init
|
||||
.type runtime_init,%function
|
||||
.thumb_func
|
||||
runtime_init:
|
||||
bx lr
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// In case core 1's VTOR has already been moved into flash, we need to handle
|
||||
// core 1 reset. However, we do so by just jumping back into bootrom version of
|
||||
// wait_for_vector
|
||||
|
||||
wait_for_vector:
|
||||
ldr r0, = 'W' | ('V' << 8)
|
||||
bl rom_func_lookup
|
||||
bx r0
|
||||
|
||||
.global __get_current_exception
|
||||
.thumb_func
|
||||
__get_current_exception:
|
||||
mrs r0, ipsr
|
||||
uxtb r0, r0
|
||||
bx lr
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Stack/heap dummies to set size
|
||||
|
||||
.section .stack
|
||||
// align to allow for memory protection (although this alignment is pretty much ignored by linker script)
|
||||
.align 5
|
||||
.equ StackSize, PICO_STACK_SIZE
|
||||
.space StackSize
|
||||
|
||||
.section .heap
|
||||
.align 2
|
||||
.equ HeapSize, PICO_HEAP_SIZE
|
||||
.space HeapSize
|
10
src/rp2_common/pico_standard_link/doc.h
Normal file
10
src/rp2_common/pico_standard_link/doc.h
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* \defgroup pico_standard_link pico_standard_link
|
||||
* \brief Standard link step providing the basics for creating a runnable binary
|
||||
*
|
||||
* This includes
|
||||
* - C runtime initialization
|
||||
* - Linker scripts for 'default', 'no_flash', 'blocked_ram' and 'copy_to_ram' binaries
|
||||
* - 'Binary Information' support
|
||||
* - Linker option control
|
||||
*/
|
251
src/rp2_common/pico_standard_link/memmap_blocked_ram.ld
Normal file
251
src/rp2_common/pico_standard_link/memmap_blocked_ram.ld
Normal file
@ -0,0 +1,251 @@
|
||||
/* 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
|
||||
{
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
|
||||
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 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 : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
KEEP (*(.vectors))
|
||||
/* 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)
|
||||
|
||||
*(.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);
|
||||
|
||||
/* End of .text-like segments */
|
||||
__etext = .;
|
||||
|
||||
.ram_vector_table (COPY): {
|
||||
*(.ram_vector_table)
|
||||
} > 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);
|
||||
/* 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);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > 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);
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .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 (COPY):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
__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);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
252
src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld
Normal file
252
src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld
Normal file
@ -0,0 +1,252 @@
|
||||
/* 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
|
||||
{
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
|
||||
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 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 : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
KEEP (*(.vectors))
|
||||
}
|
||||
|
||||
.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 (COPY): {
|
||||
*(.ram_vector_table)
|
||||
} > 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);
|
||||
|
||||
|
||||
.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);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
/* __etext is the name of the .data init source pointer (...) */
|
||||
__etext = LOADADDR(.data);
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > 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);
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .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 (COPY):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
__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);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
251
src/rp2_common/pico_standard_link/memmap_default.ld
Normal file
251
src/rp2_common/pico_standard_link/memmap_default.ld
Normal file
@ -0,0 +1,251 @@
|
||||
/* 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
|
||||
{
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
|
||||
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 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 : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
KEEP (*(.vectors))
|
||||
/* 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)
|
||||
|
||||
*(.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);
|
||||
|
||||
/* End of .text-like segments */
|
||||
__etext = .;
|
||||
|
||||
.ram_vector_table (COPY): {
|
||||
*(.ram_vector_table)
|
||||
} > 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);
|
||||
/* 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);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > 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);
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .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 (COPY):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
__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);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
213
src/rp2_common/pico_standard_link/memmap_no_flash.ld
Normal file
213
src/rp2_common/pico_standard_link/memmap_no_flash.ld
Normal file
@ -0,0 +1,213 @@
|
||||
/* 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
|
||||
{
|
||||
/* Watchdog reboot into RAM (via USB MSD will enter) 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.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
/* reset should come first */
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
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 : {
|
||||
*(.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 : {
|
||||
/* End of .text-like segments */
|
||||
__etext = .;
|
||||
__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);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > 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);
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .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 (COPY):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.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);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
26
src/rp2_common/pico_standard_link/new_delete.cpp
Normal file
26
src/rp2_common/pico_standard_link/new_delete.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#if !PICO_CXX_ENABLE_EXCEPTIONS
|
||||
// Override the standard allocators to use regular malloc/free
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
void *operator new(std::size_t n) {
|
||||
return std::malloc(n);
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t n) {
|
||||
return std::malloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *p, std::size_t n) noexcept { std::free(p); }
|
||||
|
||||
void operator delete(void *p) { std::free(p); }
|
||||
|
||||
void operator delete[](void *p) noexcept { std::free(p); }
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user