Application: Hardware Dependency and Linker Script Generation - 2024.1 English

Porting Guide for embeddedsw Components System Device Tree Based Build Flow (UG1647)

Document ID
UG1647
Release Date
2024-06-21
Version
2024.1 English

The <Component>Example.cmake file is an auto-generated file inside the library and application's src folders. It contains the required peripheral information in the CMAKE format. The Lopper backends deduce the required peripherals data mentioned under the "depends" section from the system device tree and retains them in the Example.cmake file. The CMakeLists.txt located in the src folder includes these data into the build system and generates the required software level configurations.

For applications, the CMAKE also contains the available memory related information which translates into the linker script. Together with the lscript.ld.in file, the CMAKE results into the lscript.ld file for the final application.

Sample Dependencies and Linker Sections

depends:
    emaclite:
        - reg
        - interrupts
    axiethernet:
        - reg
        - interrupts
    emacps:
        - reg
        - interrupts
    tmrctr:
        - reg
        - interrupts
    ttcps:
        - reg
        - interrupts
 
# Linker Constraints belong only to Application.
linker_constraints:
    stack: 0xA000
    heap: 0xA000

Sample Lwip_echo_serverExample.cmake

set(AXIETHERNET_NUM_DRIVER_INSTANCES "")
set(EMACLITE_NUM_DRIVER_INSTANCES "")
set(EMACPS_NUM_DRIVER_INSTANCES "CIPS_0_pspmc_0_psv_ethernet_0;CIPS_0_pspmc_0_psv_ethernet_1")
set(EMACPS0_PROP_LIST "0xff0c0000;0x4038")
list(APPEND TOTAL_EMACPS_PROP_LIST EMACPS0_PROP_LIST)
set(EMACPS1_PROP_LIST "0xff0d0000;0x403a")
list(APPEND TOTAL_EMACPS_PROP_LIST EMACPS1_PROP_LIST)
set(TMRCTR_NUM_DRIVER_INSTANCES "")
set(TTCPS_NUM_DRIVER_INSTANCES "")
set(DDR axi_noc_0)
set(axi_noc_DDR_CH_1 "0x50000000000;0x200000000")
set(axi_noc_1 "0x800000000;0x180000000")
set(axi_noc_0 "0x0;0x80000000")
set(psv_ocm_0 "0xfffc0000;0x40000")
set(TOTAL_MEM_CONTROLLERS "axi_noc_DDR_CH_1;axi_noc_1;axi_noc_0;psv_ocm_0")
set(MEMORY_SECTION "MEMORY
{
    psv_pmc_ram_psv_pmc_ram : ORIGIN = 0xF2000000, LENGTH = 0x20000
    psv_r5_0_atcm_global_MEM_0 : ORIGIN = 0xFFE00000, LENGTH = 0x40000
    psv_r5_1_atcm_global_MEM_0 : ORIGIN = 0xFFE90000, LENGTH = 0x10000
    psv_r5_1_btcm_global_MEM_0 : ORIGIN = 0xFFEB0000, LENGTH = 0x10000
    axi_noc_DDR_CH_1 : ORIGIN = 0x50000000000, LENGTH = 0x200000000
    axi_noc_1 : ORIGIN = 0x800000000, LENGTH = 0x180000000
    axi_noc_0 : ORIGIN = 0x0, LENGTH = 0x80000000
    psv_ocm_0 : ORIGIN = 0xfffc0000, LENGTH = 0x40000
}")
set(STACK_SIZE 0xa000)
set(HEAP_SIZE 0xa000)

Sample lscript.ld.in File

_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : @STACK_SIZE@;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : @HEAP_SIZE@;
 
_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024;
_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048;
_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
 
@MEMORY_SECTION@
 
/* Specify the default entry point to the program */
 
ENTRY(_vector_table)
 
/* Define the sections, and where they are mapped in memory */
 
SECTIONS
{
.text : {
   KEEP (*(.vectors))
   *(.boot)
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   *(.gnu_warning)
   *(.gcc_execpt_table)
   *(.glue_7)
   *(.glue_7t)
   *(.ARM.extab)
   *(.gnu.linkonce.armextab.*)
} > @DDR@
 
.init (ALIGN(64)) : {
   KEEP (*(.init))
} > @DDR@
 
.fini (ALIGN(64)) : {
   KEEP (*(.fini))
} > @DDR@
 
.interp : {
   KEEP (*(.interp))
} > @DDR@
 
.note-ABI-tag : {
   KEEP (*(.note-ABI-tag))
} > @DDR@
 
.rodata : {
   . = ALIGN(64);
   __rodata_start = .;
   *(.rodata)
   *(.rodata.*)
   *(.gnu.linkonce.r.*)
   __rodata_end = .;
} > @DDR@
 
.rodata1 : {
   . = ALIGN(64);
   __rodata1_start = .;
   *(.rodata1)
   *(.rodata1.*)
   __rodata1_end = .;
} > @DDR@
 
.sdata2 : {
   . = ALIGN(64);
   __sdata2_start = .;
   *(.sdata2)
   *(.sdata2.*)
   *(.gnu.linkonce.s2.*)
   __sdata2_end = .;
} > @DDR@
 
.sbss2 : {
   . = ALIGN(64);
   __sbss2_start = .;
   *(.sbss2)
   *(.sbss2.*)
   *(.gnu.linkonce.sb2.*)
   __sbss2_end = .;
} > @DDR@
 
.data : {
   . = ALIGN(64);
   __data_start = .;
   *(.data)
   *(.data.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
   __data_end = .;
} > @DDR@
 
.data1 : {
   . = ALIGN(64);
   __data1_start = .;
   *(.data1)
   *(.data1.*)
   __data1_end = .;
} > @DDR@
 
.got : {
   *(.got)
} > @DDR@
 
.got1 : {
   *(.got1)
} > @DDR@
 
.got2 : {
   *(.got2)
} > @DDR@
 
.ctors : {
   . = ALIGN(64);
   __CTOR_LIST__ = .;
   ___CTORS_LIST___ = .;
   KEEP (*crtbegin.o(.ctors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
   KEEP (*(SORT(.ctors.*)))
   KEEP (*(.ctors))
   __CTOR_END__ = .;
   ___CTORS_END___ = .;
} > @DDR@
 
.dtors : {
   . = ALIGN(64);
   __DTOR_LIST__ = .;
   ___DTORS_LIST___ = .;
   KEEP (*crtbegin.o(.dtors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
   KEEP (*(SORT(.dtors.*)))
   KEEP (*(.dtors))
   __DTOR_END__ = .;
   ___DTORS_END___ = .;
} > @DDR@
 
.fixup : {
   __fixup_start = .;
   *(.fixup)
   __fixup_end = .;
} > @DDR@
 
.eh_frame : {
   *(.eh_frame)
} > @DDR@
 
.eh_framehdr : {
   __eh_framehdr_start = .;
   *(.eh_framehdr)
   __eh_framehdr_end = .;
} > @DDR@
 
.gcc_except_table : {
   *(.gcc_except_table)
} > @DDR@
 
.mmu_tbl0 (ALIGN(4096)) : {
   __mmu_tbl0_start = .;
   *(.mmu_tbl0)
   __mmu_tbl0_end = .;
} > @DDR@
 
.mmu_tbl1 (ALIGN(4096)) : {
   __mmu_tbl1_start = .;
   *(.mmu_tbl1)
   __mmu_tbl1_end = .;
} > @DDR@
 
.mmu_tbl2 (ALIGN(4096)) : {
   __mmu_tbl2_start = .;
   *(.mmu_tbl2)
   __mmu_tbl2_end = .;
} > @DDR@
 
.ARM.exidx : {
   __exidx_start = .;
   *(.ARM.exidx*)
   *(.gnu.linkonce.armexidix.*.*)
   __exidx_end = .;
} > @DDR@
 
.preinit_array : {
   . = ALIGN(64);
   __preinit_array_start = .;
   KEEP (*(SORT(.preinit_array.*)))
   KEEP (*(.preinit_array))
   __preinit_array_end = .;
} > @DDR@
 
.init_array : {
   . = ALIGN(64);
   __init_array_start = .;
   KEEP (*(SORT(.init_array.*)))
   KEEP (*(.init_array))
   __init_array_end = .;
} > @DDR@
 
.fini_array : {
   . = ALIGN(64);
   __fini_array_start = .;
   KEEP (*(SORT(.fini_array.*)))
   KEEP (*(.fini_array))
   __fini_array_end = .;
} > @DDR@
 
.drvcfg_sec : {
    . = ALIGN(8);
     __drvcfgsecdata_start = .;
    KEEP (*(.drvcfg_sec))
    __drvcfgsecdata_end = .;
    __drvcfgsecdata_size = __drvcfgsecdata_end - __drvcfgsecdata_start;
} > @DDR@
 
.ARM.attributes : {
   __ARM.attributes_start = .;
   *(.ARM.attributes)
   __ARM.attributes_end = .;
} > @DDR@
 
.sdata : {
   . = ALIGN(64);
   __sdata_start = .;
   *(.sdata)
   *(.sdata.*)
   *(.gnu.linkonce.s.*)
   __sdata_end = .;
} > @DDR@
 
.sbss (NOLOAD) : {
   . = ALIGN(64);
   __sbss_start = .;
   *(.sbss)
   *(.sbss.*)
   *(.gnu.linkonce.sb.*)
   . = ALIGN(64);
   __sbss_end = .;
} > @DDR@
 
.tdata : {
   . = ALIGN(64);
   __tdata_start = .;
   *(.tdata)
   *(.tdata.*)
   *(.gnu.linkonce.td.*)
   __tdata_end = .;
} > @DDR@
 
.tbss : {
   . = ALIGN(64);
   __tbss_start = .;
   *(.tbss)
   *(.tbss.*)
   *(.gnu.linkonce.tb.*)
   __tbss_end = .;
} > @DDR@
 
.bss (NOLOAD) : {
   . = ALIGN(64);
   __bss_start__ = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   . = ALIGN(64);
   __bss_end__ = .;
} > @DDR@
 
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
 
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
 
/* Generate Stack and Heap definitions */
 
.heap (NOLOAD) : {
   . = ALIGN(64);
   _heap = .;
   HeapBase = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
   HeapLimit = .;
} > @DDR@
 
.stack (NOLOAD) : {
   . = ALIGN(64);
   _el3_stack_end = .;
   . += _STACK_SIZE;
   __el3_stack = .;
   _el2_stack_end = .;
   . += _EL2_STACK_SIZE;
   . = ALIGN(64);
   __el2_stack = .;
   _el1_stack_end = .;
   . += _EL1_STACK_SIZE;
   . = ALIGN(64);
   __el1_stack = .;
   _el0_stack_end = .;
   . += _EL0_STACK_SIZE;
   . = ALIGN(64);
   __el0_stack = .;
} > @DDR@
 
 
_end = .;
}