Загрузка данных
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
M_VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x0620 : 0x0;
/*
Карта памяти i.MX 95 DDR строго синхронизированная с файлом DTS Linux.
Адресация прямая, без смещений между ядрами A55 и M7.
*/
MEMORY
{
/* Таблица ресурсов: Строго по адресу rsc_table из DTS */
m_rsc_tbl (RW) : ORIGIN = 0x88220000, LENGTH = 0x00001000
/* ISR vectors: Таблица векторов прерываний М7 в начале вашего 8МБ окна */
m_interrupts (RX) : ORIGIN = 0x88320000, LENGTH = 0x00000800
/* Program code: Код программы и константы (4 Mb - 2 Kb) */
m_text (RX) : ORIGIN = 0x88320800, LENGTH = 0x003FF800
/* Data: Переменные, стек и динамическая куча в оставшейся части 8МБ окна (4 Mb) */
m_data (RW) : ORIGIN = 0x88720000, LENGTH = 0x00400000
/* Ncache: Буферы RPMSG, посаченные точно на регион vdevbuffer из DTS */
m_ncache (RW) : ORIGIN = 0x88020000, LENGTH = 0x00100000
}
/* Define output sections */
SECTIONS
{
__NCACHE_REGION_START = ORIGIN(m_ncache);
__NCACHE_REGION_SIZE = LENGTH(m_ncache);
/* Вектора прерываний в начале выделенной под код памяти */
.interrupts :
{
__VECTOR_TABLE = .;
__Vectors = .;
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} > m_interrupts
/*
Таблица ресурсов для взаимодействия с Linux Remoteproc.
Она вынесена в отдельный регион памяти, жестко согласованный с DTS.
*/
.resource_table :
{
. = ALIGN(8);
KEEP(*(.resource_table))
. = ALIGN(8);
} > m_rsc_tbl
/* Исполняемый код программы и константы */
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
__quickcodeaccess_start__ = .;
. = ALIGN(32);
*(CodeQuickAccess)
. = ALIGN(32);
__quickcodeaccess_end__ = .;
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
.ctors :
{
__CTOR_LIST__ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text
.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text
__etext = .;
__DATA_ROM = .;
/* Секция векторов прерываний в ОЗУ (внутри m_data) */
.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__interrupts_ram_start__ = .;
*(.m_interrupts_ram)
. += M_VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .;
} > m_data
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
/* Инициализированные глобальные и статические переменные (внутри m_data) */
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .;
__quickdataaccess_start__ = .;
. = ALIGN(32);
*(DataQuickAccess)
. = ALIGN(32);
__quickdataaccess_end__ = .;
*(.data)
*(.data*)
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .;
} > m_data
__NDATA_ROM = __DATA_ROM + SIZEOF(.data);
/* Инициализируемые некэшируемые структуры данных межъядерного обмена */
.ncache.init : AT(__NDATA_ROM)
{
__noncachedata_start__ = .;
*(NonCacheable.init)
. = ALIGN(4);
__noncachedata_init_end__ = .;
} > m_ncache
. = __noncachedata_init_end__;
/* Стандартные некэшируемые буферы очередей RPMSG */
.ncache :
{
*(NonCacheable)
. = ALIGN(4);
__noncachedata_end__ = .;
} > m_ncache
__DATA_END = __NDATA_ROM + SIZEOF(.ncache.init);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
/* Глобальные неинициализированные переменные (.bss автоматически растет в m_data) */
.bss :
{
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
/* Выделение динамической кучи (Heap) внутри m_data */
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .;
} > m_data
/* Выделение стека функций (Stack) внутри m_data */
.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data
/* Расчет верхушки стека от верхней физической границы пула m_data */
__StackTop = ORIGIN(m_data) + LENGTH(m_data);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
/* Алиасы для обратной совместимости с драйверами SDK */
__RscTblStart = ORIGIN(m_rsc_tbl);
__RscTblEnd = ORIGIN(m_rsc_tbl) + LENGTH(m_rsc_tbl);
__RscTblInDramStart = ORIGIN(m_rsc_tbl);
__RscTblInDramEnd = ORIGIN(m_rsc_tbl) + LENGTH(m_rsc_tbl);
/*
ДОБАВЛЕННЫЕ СЛУЖЕБНЫЕ ПОЛЯ ДЛЯ ПОДСИСТЕМЫ ПИТАНИЯ SDK (lpm.c)
Исключают ошибки undefined reference при линковке power_mode_switch
*/
__RESERVED_START = ORIGIN(m_interrupts);
__RESERVED_END = ORIGIN(m_text) + LENGTH(m_text);
__VECTOR_TABLE_SIZE_BYTES = LENGTH(m_interrupts);
.ARM.attributes 0 : { *(.ARM.attributes) }
ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}