universalisos/microkernel/ports/esp32/linker.ld

90 lines
2.2 KiB
Text

/*
* UniversalisOS Microkernel — ESP32 Linker Script
*
* Memory layout (ESP32-D0WDQ6):
* IRAM: 0x40080000-0x400A0000 (128KB) — code + vectors
* DRAM: 0x3FFB0000-0x3FFC0000 (64KB) — data + stacks
*
* Section layout:
* .vectors — Exception/interrupt vector table (MUST be first)
* .text.startup — Startup code
* .text — Kernel code
* .rodata — Read-only data
* .data — Initialized data
* .bss — Uninitialized data
* .stack — Main stack
*/
ENTRY(_start)
MEMORY {
IRAM (rwx) : ORIGIN = 0x40080000, LENGTH = 128K
DRAM (rw) : ORIGIN = 0x3FFB0000, LENGTH = 128K
}
_estack = ORIGIN(DRAM) + LENGTH(DRAM);
SECTIONS {
/* Vector table — MUST be at VECBASE (start of IRAM) */
.vectors : {
. = ALIGN(4);
_vectors_start = .;
KEEP(*(.vectors))
. = ALIGN(4);
_vectors_end = .;
} > IRAM
/* Startup code (optional, after vectors) */
.text.startup : {
. = ALIGN(4);
*(.text.startup)
. = ALIGN(4);
} > IRAM
/* Kernel code + literal pools + rodata (all in IRAM for I-bus access).
* NOTE: With -mtext-section-literals, string constants go inline in .text.
* D-bus reads of IRAM addresses will fault — code must NOT dereference
* string pointers from IRAM. Use direct UART register writes instead. */
.text : {
. = ALIGN(4);
*(.text)
*(.text*)
*(.literal)
*(.literal*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} > IRAM
/* Initialized data (copied from flash to DRAM at startup) */
_sidata = LOADADDR(.data);
.data : {
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} > DRAM AT> IRAM
/* Uninitialized data */
.bss : {
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > DRAM
/* Stack (4KB, grows downward) */
.stack (NOLOAD) : {
. = ALIGN(16);
. += 4K;
. = ALIGN(16);
} > DRAM
}
/* Espressif ROM UART function */
PROVIDE(uart_tx_one_char = 0x40009200);