215 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /* # EMBASSY notes
 | |
|   This file is a workaround for https://github.com/rust-embedded/riscv/issues/196
 | |
|   Remove when fixed upstream.
 | |
| */
 | |
| /* # Developer notes
 | |
| 
 | |
| - Symbols that start with a double underscore (__) are considered "private"
 | |
| 
 | |
| - Symbols that start with a single underscore (_) are considered "semi-public"; they can be
 | |
|   overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" {
 | |
|   static mut _heap_size }`).
 | |
| 
 | |
| - `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a
 | |
|   symbol if not dropped if it appears in or near the front of the linker arguments and "it's not
 | |
|   needed" by any of the preceding objects (linker arguments)
 | |
| 
 | |
| - `PROVIDE` is used to provide default values that can be overridden by a user linker script
 | |
| 
 | |
| - In this linker script, you may find symbols that look like `${...}` (e.g., `4`).
 | |
|   These are wildcards used by the `build.rs` script to adapt to different target particularities.
 | |
|   Check `build.rs` for more details about these symbols.
 | |
| 
 | |
| - On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and*
 | |
|   the LMA of .data are all `4`-byte aligned. These alignments are assumed by the RAM
 | |
|   initialization routine. There's also a second benefit: `4`-byte aligned boundaries
 | |
|   means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
 | |
| */
 | |
| 
 | |
| PROVIDE(_stext = ORIGIN(REGION_TEXT));
 | |
| PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
 | |
| PROVIDE(_max_hart_id = 0);
 | |
| PROVIDE(_hart_stack_size = 2K);
 | |
| PROVIDE(_heap_size = 0);
 | |
| 
 | |
| PROVIDE(InstructionMisaligned = ExceptionHandler);
 | |
| PROVIDE(InstructionFault = ExceptionHandler);
 | |
| PROVIDE(IllegalInstruction = ExceptionHandler);
 | |
| PROVIDE(Breakpoint = ExceptionHandler);
 | |
| PROVIDE(LoadMisaligned = ExceptionHandler);
 | |
| PROVIDE(LoadFault = ExceptionHandler);
 | |
| PROVIDE(StoreMisaligned = ExceptionHandler);
 | |
| PROVIDE(StoreFault = ExceptionHandler);;
 | |
| PROVIDE(UserEnvCall = ExceptionHandler);
 | |
| PROVIDE(SupervisorEnvCall = ExceptionHandler);
 | |
| PROVIDE(MachineEnvCall = ExceptionHandler);
 | |
| PROVIDE(InstructionPageFault = ExceptionHandler);
 | |
| PROVIDE(LoadPageFault = ExceptionHandler);
 | |
| PROVIDE(StorePageFault = ExceptionHandler);
 | |
| 
 | |
| PROVIDE(SupervisorSoft = DefaultHandler);
 | |
| PROVIDE(MachineSoft = DefaultHandler);
 | |
| PROVIDE(SupervisorTimer = DefaultHandler);
 | |
| PROVIDE(MachineTimer = DefaultHandler);
 | |
| PROVIDE(SupervisorExternal = DefaultHandler);
 | |
| PROVIDE(MachineExternal = DefaultHandler);
 | |
| 
 | |
| PROVIDE(DefaultHandler = DefaultInterruptHandler);
 | |
| PROVIDE(ExceptionHandler = DefaultExceptionHandler);
 | |
| 
 | |
| /* # Pre-initialization function */
 | |
| /* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function,
 | |
|    then the function this points to will be called before the RAM is initialized. */
 | |
| PROVIDE(__pre_init = default_pre_init);
 | |
| 
 | |
| /* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
 | |
| PROVIDE(_setup_interrupts = default_setup_interrupts);
 | |
| 
 | |
| /* # Multi-processing hook function
 | |
|    fn _mp_hook() -> bool;
 | |
| 
 | |
|    This function is called from all the harts and must return true only for one hart,
 | |
|    which will perform memory initialization. For other harts it must return false
 | |
|    and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).
 | |
| */
 | |
| PROVIDE(_mp_hook = default_mp_hook);
 | |
| 
 | |
| /* # Start trap function override
 | |
|   By default uses the riscv crates default trap handler
 | |
|   but by providing the `_start_trap` symbol external crates can override.
 | |
| */
 | |
| PROVIDE(_start_trap = default_start_trap);
 | |
| 
 | |
| SECTIONS
 | |
| {
 | |
|   .text.dummy (NOLOAD) :
 | |
|   {
 | |
|     /* This section is intended to make _stext address work */
 | |
|     . = ABSOLUTE(_stext);
 | |
|   } > REGION_TEXT
 | |
| 
 | |
|   .text _stext :
 | |
|   {
 | |
|     /* Put reset handler first in .text section so it ends up as the entry */
 | |
|     /* point of the program. */
 | |
|     KEEP(*(.init));
 | |
|     KEEP(*(.init.rust));
 | |
|     . = ALIGN(4);
 | |
|     *(.trap);
 | |
|     *(.trap.rust);
 | |
|     *(.text.abort);
 | |
|     *(.text .text.*);
 | |
|   } > REGION_TEXT
 | |
| 
 | |
|   .eh_frame : { KEEP(*(.eh_frame)) } > REGION_TEXT
 | |
|   .eh_frame_hdr : { *(.eh_frame_hdr) } > REGION_TEXT
 | |
| 
 | |
|   .rodata : ALIGN(4)
 | |
|   {
 | |
|     *(.srodata .srodata.*);
 | |
|     *(.rodata .rodata.*);
 | |
| 
 | |
|     /* 4-byte align the end (VMA) of this section.
 | |
|        This is required by LLD to ensure the LMA of the following .data
 | |
|        section will have the correct alignment. */
 | |
|     . = ALIGN(4);
 | |
|   } > REGION_RODATA
 | |
| 
 | |
|   .data : ALIGN(4)
 | |
|   {
 | |
|     _sidata = LOADADDR(.data);
 | |
|     _sdata = .;
 | |
|     /* Must be called __global_pointer$ for linker relaxations to work. */
 | |
|     PROVIDE(__global_pointer$ = . + 0x800);
 | |
|     *(.sdata .sdata.* .sdata2 .sdata2.*);
 | |
|     *(.data .data.*);
 | |
|     . = ALIGN(4);
 | |
|     _edata = .;
 | |
|   } > REGION_DATA AT > REGION_RODATA
 | |
| 
 | |
|   .bss (NOLOAD) : ALIGN(4)
 | |
|   {
 | |
|     _sbss = .;
 | |
|     *(.sbss .sbss.* .bss .bss.*);
 | |
|     . = ALIGN(4);
 | |
|     _ebss = .;
 | |
|   } > REGION_BSS
 | |
| 
 | |
|   /* fictitious region that represents the memory available for the heap */
 | |
|   .heap (NOLOAD) :
 | |
|   {
 | |
|     _sheap = .;
 | |
|     . += _heap_size;
 | |
|     . = ALIGN(4);
 | |
|     _eheap = .;
 | |
|   } > REGION_HEAP
 | |
| 
 | |
|   /* fictitious region that represents the memory available for the stack */
 | |
|   .stack (NOLOAD) :
 | |
|   {
 | |
|     _estack = .;
 | |
|     . = ABSOLUTE(_stack_start);
 | |
|     _sstack = .;
 | |
|   } > REGION_STACK
 | |
| 
 | |
|   /* fake output .got section */
 | |
|   /* Dynamic relocations are unsupported. This section is only used to detect
 | |
|      relocatable code in the input files and raise an error if relocatable code
 | |
|      is found */
 | |
|   .got (INFO) :
 | |
|   {
 | |
|     KEEP(*(.got .got.*));
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Do not exceed this mark in the error messages above                                    | */
 | |
| ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
 | |
| ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(_stext % 4 == 0, "
 | |
| ERROR(riscv-rt): `_stext` must be 4-byte aligned");
 | |
| 
 | |
| ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
 | |
| BUG(riscv-rt): .data is not 4-byte aligned");
 | |
| 
 | |
| ASSERT(_sidata % 4 == 0, "
 | |
| BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
 | |
| 
 | |
| ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, "
 | |
| BUG(riscv-rt): .bss is not 4-byte aligned");
 | |
| 
 | |
| ASSERT(_sheap % 4 == 0, "
 | |
| BUG(riscv-rt): start of .heap is not 4-byte aligned");
 | |
| 
 | |
| ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
 | |
| ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
 | |
| Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
 | |
| 
 | |
| ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
 | |
| ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
 | |
| Consider changing `_max_hart_id` or `_hart_stack_size`.");
 | |
| 
 | |
| ASSERT(SIZEOF(.got) == 0, "
 | |
| .got section detected in the input files. Dynamic relocations are not
 | |
| supported. If you are linking to C code compiled using the `gcc` crate
 | |
| then modify your build script to compile the C code _without_ the
 | |
| -fPIC flag. See the documentation of the `gcc::Config.fpic` method for
 | |
| details.");
 | |
| 
 | |
| /* Do not exceed this mark in the error messages above                                    | */
 |