esp-hal/esp32c3-hal/ld/db-riscv-link.x
sethp 171e66e87a
feat(riscv): relocate .trap machinery to RAM (#541)
* feat: relocate riscv isr to iram

Previously, the trap vector itself and its immediate callees
(`_start_trap` and `_start_trap_rust_hal`) were located in the mapped
instruction flash range `0x420..`, increasing cache pressure and adding
variable latency to the very beginning of the interrupt/exception
service flow.

This change places those routines in iram directly:

```
   Num:    Value  Size Type    Bind   Vis      Ndx Name
 48177: 40380280  2428 FUNC    GLOBAL DEFAULT    6 _start_trap_rust_hal
 48197: 40380bfc    54 FUNC    GLOBAL DEFAULT    6 _start_trap_rust
 48265: 40380200     0 FUNC    GLOBAL DEFAULT    6 _vector_table
 48349: 40380100     0 NOTYPE  GLOBAL DEFAULT    6 default_start_trap
 48350: 40380100     0 NOTYPE  GLOBAL DEFAULT    6 _start_trap
```

As seen via `readelf -W -s -C ./target/riscv32imc-unknown-none-elf/debug/examples/gpio_interrupt | grep -E _start_trap\|_vector\|Ndx`

* feat(riscv): place .trap in RAM

This change follows through on relocating the `_vector_table`,
`_start_trap`, and `_start_trap_rust` functions for all present
build/link modes for the 'c2, 'c3, 'c6, and 'h2.

It has been tested by running the `software_interrupts` example for the
'c3 in direct-boot and esp-bootloader contexts, but I wasn't able to
identify how to run the `mcu-boot` mode for the 'c3, nor do I have
present access to any of the other devices for testing.

* docs: Update CHANGELOG.md
2023-05-26 20:48:49 +01:00

241 lines
7.4 KiB
Plaintext

ENTRY(_start)
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(UserSoft = DefaultHandler);
PROVIDE(SupervisorSoft = DefaultHandler);
PROVIDE(MachineSoft = DefaultHandler);
PROVIDE(UserTimer = DefaultHandler);
PROVIDE(SupervisorTimer = DefaultHandler);
PROVIDE(MachineTimer = DefaultHandler);
PROVIDE(UserExternal = DefaultHandler);
PROVIDE(SupervisorExternal = DefaultHandler);
PROVIDE(MachineExternal = DefaultHandler);
PROVIDE(DefaultHandler = DefaultInterruptHandler);
PROVIDE(ExceptionHandler = DefaultExceptionHandler);
PROVIDE(__post_init = default_post_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));
KEEP(*(.text.abort));
. = ALIGN(4);
*(.text .text.*);
_etext = .;
} > REGION_TEXT
_text_size = _etext - _stext + 8;
.rodata ORIGIN(DROM) + _text_size : AT(_text_size)
{
_srodata = .;
*(.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);
_erodata = .;
} > REGION_RODATA
_rodata_size = _erodata - _srodata + 8;
.data ORIGIN(DRAM) : AT(_text_size + _rodata_size)
{
_data_start = .;
/* Must be called __global_pointer$ for linker relaxations to work. */
PROVIDE(__global_pointer$ = . + 0x800);
*(.sdata .sdata.* .sdata2 .sdata2.*);
*(.data .data.*);
. = ALIGN(4);
_data_end = .;
} > REGION_DATA
_data_size = _data_end - _data_start + 8;
.rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){
_srwtext = .;
*(.rwtext);
. = ALIGN(4);
KEEP(*(.trap));
*(.trap.*);
_erwtext = .;
} > REGION_RWTEXT
_rwtext_size = _erwtext - _srwtext + 8;
.rwtext.dummy (NOLOAD):
{
/* This section is required to skip .rwtext area because REGION_RWTEXT
* and REGION_BSS reflect the same address space on different buses.
*/
. = ORIGIN(REGION_DATA) + _rwtext_size + 8 + SIZEOF(.data);
} > REGION_DATA
.bss (NOLOAD) :
{
_bss_start = .;
*(.sbss .sbss.* .bss .bss.*);
. = ALIGN(4);
_bss_end = .;
} > REGION_BSS
/* ### .uninit */
.uninit (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__suninit = .;
*(.uninit .uninit.*);
. = ALIGN(4);
__euninit = .;
} > 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
.rtc_fast.text : AT(_text_size + _rodata_size + _data_size + _rwtext_size) {
_srtc_fast_text = .;
*(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*)
. = ALIGN(4);
_ertc_fast_text = .;
} > REGION_RTC_FAST
_fast_text_size = _ertc_fast_text - _srtc_fast_text + 8;
.rtc_fast.data : AT(_text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size)
{
_rtc_fast_data_start = ABSOLUTE(.);
*(.rtc_fast.data .rtc_fast.data.*)
. = ALIGN(4);
_rtc_fast_data_end = ABSOLUTE(.);
} > REGION_RTC_FAST
_rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start + 8;
.rtc_fast.bss (NOLOAD) : ALIGN(4)
{
_rtc_fast_bss_start = ABSOLUTE(.);
*(.rtc_fast.bss .rtc_fast.bss.*)
. = ALIGN(4);
_rtc_fast_bss_end = ABSOLUTE(.);
} > REGION_RTC_FAST
.rtc_fast.noinit (NOLOAD) : ALIGN(4)
{
*(.rtc_fast.noinit .rtc_fast.noinit.*)
} > REGION_RTC_FAST
/* 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.*));
}
.eh_frame (INFO) : { KEEP(*(.eh_frame)) }
.eh_frame_hdr (INFO) : { *(.eh_frame_hdr) }
}
PROVIDE(_sidata = _erodata + 8);
PROVIDE(_irwtext = ORIGIN(DROM) + _text_size + _rodata_size + _data_size);
PROVIDE(_irtc_fast_text = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size);
PROVIDE(_irtc_fast_data = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size);
/* 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(_data_start % 4 == 0 && _data_end % 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(_bss_start % 4 == 0 && _bss_end % 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 | */