FreeRTOS-Kernel/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.freertos.lds
Gaurav-Aggarwal-AWS 2fedeff332
Update BSP and SDK for HiFive board (#645)
* Update BSP and SDK for HiFive board

This commit also adds demo start and success/failure output messages.
2021-07-15 18:40:22 -07:00

327 lines
No EOL
11 KiB
Text

/* Copyright (c) 2020 SiFive Inc. */
/* SPDX-License-Identifier: Apache-2.0 */
OUTPUT_ARCH("riscv")
/* Privileged mode Linker Script
*
* This linker script is based on metal.default.lds. It introduce specific
* section to isolate (acessible only from machine mode) and others that can be
* used in every execution mode. This linker script it tailored for FreeRTOS
* applications.
*/
ENTRY(_enter)
MEMORY
{
itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
}
PHDRS
{
rom PT_LOAD;
ram_init PT_LOAD;
tls PT_TLS;
ram PT_LOAD;
itim_init PT_LOAD;
text PT_LOAD;
lim_init PT_LOAD;
}
SECTIONS
{
/* Each hart is allocated its own stack of size __stack_size. This value
* can be overriden at build-time by adding the following to CFLAGS:
*
* -Xlinker --defsym=__stack_size=0xf00
*
* where 0xf00 can be replaced with a multiple of 16 of your choice.
*
* __stack_size is PROVIDE-ed as a symbol so that initialization code
* initializes the stack pointers for each hart at the right offset from
* the _sp symbol.
*/
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
PROVIDE(__stack_size = __stack_size);
/* The size of the heap can be overriden at build-time by adding the
* following to CFLAGS:
*
* -Xlinker --defsym=__heap_size=0xf00
*
* where 0xf00 can be replaced with the value of your choice.
*
* Altertatively, the heap can be grown to fill the entire remaining region
* of RAM by adding the following to CFLAGS:
*
* -Xlinker --defsym=__heap_max=1
*
* Note that depending on the memory layout, the bitness (32/64bit) of the
* target, and the code model in use, this might cause a relocation error.
*/
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
/* The boot hart sets which hart runs the pre-main initialization routines,
* including copying .data into RAM, zeroing the BSS region, running
* constructors, etc. After initialization, the boot hart is also the only
* hart which runs application code unless the application overrides the
* secondary_main() function to start execution on secondary harts.
*/
PROVIDE(__metal_boot_hart = 0);
/* The chicken bit is used by pre-main initialization to enable/disable
* certain core features */
PROVIDE(__metal_chicken_bit = 1);
/* The memory_ecc_scrub bit is used by _entry code to enable/disable
* memories scrubbing to zero */
PROVIDE(__metal_eccscrub_bit = 0);
/* The RAM memories map for ECC scrubbing */
PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
PROVIDE( metal_itim_0_memory_start = 0x8000000 );
PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
/* ROM SECTION
*
* The following sections contain data which lives in read-only memory, if
* such memory is present in the design, for the entire duration of program
* execution.
*/
.init : {
/* The _enter symbol is placed in the .text.metal.init.enter section
* and must be placed at the beginning of the program */
KEEP (*(.text.metal.init.enter))
KEEP (*(.text.metal.init.*))
KEEP (*(SORT_NONE(.init)))
KEEP (*(.text.libgloss.start))
} >rom :rom
.fini : {
KEEP (*(SORT_NONE(.fini)))
} >rom :rom
.preinit_array : ALIGN(8) {
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >rom :rom
.init_array : ALIGN(8) {
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
PROVIDE_HIDDEN ( metal_constructors_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
KEEP (*(.metal.init_array));
PROVIDE_HIDDEN ( metal_constructors_end = .);
} >rom :rom
.fini_array : ALIGN(8) {
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
PROVIDE_HIDDEN ( metal_destructors_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
KEEP (*(.metal.fini_array));
PROVIDE_HIDDEN ( metal_destructors_end = .);
} >rom :rom
.privileged_functions : ALIGN (32) {
__privileged_functions_start__ = .;
KEEP(*(privileged_functions))
. = ALIGN(32);
__privileged_functions_end__ = .;
} >rom
.ctors : {
. = ALIGN(32);
__unprivileged_section_start__ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*(.metal.ctors .metal.ctors.*))
} >rom :rom
.dtors : {
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
KEEP (*(.metal.dtors .metal.dtors.*))
} >rom : rom
.rodata : {
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >rom :rom
/* ITIM SECTION
*
* The following sections contain data which is copied from read-only
* memory into an instruction tightly-integrated memory (ITIM), if one
* is present in the design, during pre-main program initialization.
*
* Generally, the data copied into the ITIM should be performance-critical
* functions which benefit from low instruction-fetch latency.
*/
.itim : ALIGN(8) {
*(.itim .itim.*)
} >itim AT>rom :itim_init
PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
/* LIM SECTION
*
* The following sections contain data which is copied from read-only
* memory into a loosely integrated memory (LIM), which is shared with L2
* cache, during pre-main program initialization.
*
* Generally, the data copied into the LIM should be performance-critical
* functions which benefit from low instruction-fetch latency.
*/
.lim : ALIGN(8) {
*(.lim .lim.*)
} >ram AT>rom :lim_init
PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
/* TEXT SECTION
*
* The following section contains the code of the program, excluding
* everything that's been allocated into the ITIM/LIM already
*/
.text : {
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
*(freertos_system_calls)
. = ALIGN(32);
__unprivileged_section_end__ = .;
} >rom :text
/* RAM SECTION
*
* The following sections contain data which is copied from read-only
* memory into a read-write-capable memory such as data tightly-integrated
* memory (DTIM) or another main memory, as well as the BSS, stack, and
* heap.
*
* You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
* have an apparently unnecessary ALIGN at their top. This is because
* the implementation of _start in Freedom Metal libgloss depends on the
* ADDR and LOADADDR being 8-byte aligned.
*/
.data : ALIGN(8) {
. = ALIGN(32);
__unprivileged_data_section_start__ = .;
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.* .sdata2.*)
*(.gnu.linkonce.s.*)
} >ram AT>rom :ram_init
.tdata : ALIGN(8) {
PROVIDE( __tls_base = . );
*(.tdata .tdata.* .gnu.linkonce.td.*)
} >ram AT>rom :tls :ram_init
PROVIDE( __tdata_source = LOADADDR(.tdata) );
PROVIDE( __tdata_size = SIZEOF(.tdata) );
PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
PROVIDE( metal_segment_data_target_start = ADDR(.data) );
PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
.tbss : ALIGN(8) {
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon .tcommon.*)
PROVIDE( __tls_end = . );
} >ram AT>ram :tls :ram
PROVIDE( __tbss_size = SIZEOF(.tbss) );
PROVIDE( __tls_size = __tls_end - __tls_base );
.tbss_space : ALIGN(8) {
. = . + __tbss_size;
} >ram :ram
.bss (NOLOAD): ALIGN(8) {
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(32);
__unprivileged_data_section_end__ = .;
} >ram :ram
PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
.privileged_data (NOLOAD) : ALIGN(32) {
__privileged_data_start__ = .;
*(privileged_data)
/* Non kernel data is kept out of the first _Privileged_Data_Region_Size
bytes of SRAM. */
. = ALIGN(32);
__privileged_data_end__ = .;
} >ram
.stack (NOLOAD) : ALIGN(16) {
PROVIDE(metal_segment_stack_begin = .);
. += __stack_size; /* Hart 0 */
PROVIDE( _sp = . );
PROVIDE(metal_segment_stack_end = .);
} >ram :ram
.heap (NOLOAD) : ALIGN(8) {
PROVIDE( __end = . );
PROVIDE( __heap_start = . );
PROVIDE( metal_segment_heap_target_start = . );
/* If __heap_max is defined, grow the heap to use the rest of RAM,
* otherwise set the heap size to __heap_size */
. = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
PROVIDE( metal_segment_heap_target_end = . );
PROVIDE( _heap_end = . );
PROVIDE( __heap_end = . );
} >ram :ram
/* C++ exception handling information is
* not useful with our current runtime environment,
* and it consumes flash space. Discard it until
* we have something that can use it
*/
/DISCARD/ : {
*(.eh_frame .eh_frame.*)
}
}