linker - Understanding the linkerscript for an ARM Cortex-M microcontroller -


i using stm32f746ng microcontroller stmicroelectronics. device based on arm cortex-m7 architecture. invested quite time in understanding linkerscript example projects. figured out basics, still cannot grasp big parts of it. please me understand parts.

start of linkerscript

the linkerscript starts follows:

/* entry point */ entry(reset_handler) /* function named 'reset_handler' defined */                      /* in 'startup.s' assembly file.             */  /* highest address of user mode stack */ /* remember: stack points downwards */ _estack = 0x20050000;    /* end of ram */  /* generate link error if heap , stack don't fit ram */ _min_heap_size = 0x200;  /* required amount of heap  */ _min_stack_size = 0x400; /* required amount of stack */  /* --------------------------------------------------------------------*/ /*                    memory areas                                     */ /* --------------------------------------------------------------------*/ memory {     /* flash memory */     /* ------------ */     /* remember: flash memory on device can   */     /* accessed through either axim bus or */     /* itcm bus. accesses on itcm bus start @     */     /* address 0x0020 0000. accesses on axim bus   */     /* @ address 0x0800 0000.                         */     flash (rx)     : origin = 0x08000000, length = 1024k     /* flash (rx)     : origin = 0x00200000, length = 1024k */      /* ram memory */     /* ---------- */     ram (xrw)      : origin = 0x20000000, length = 320k } 

vector table , program code

after defining memory areas, linkerscript proceeds defining sections. first section defined in linkerscript vector table. has end in first bytes of flash memory.

/* --------------------------------------------------------------------*/ /*                    output sections                                  */ /* --------------------------------------------------------------------*/ sections {     /****************************/     /*      vector table        */     /****************************/     .isr_vector :     {         . = align(4);         keep(*(.isr_vector)) /* vector table */         . = align(4);     } >flash 

after vector table inserted, it's time program code:

    /****************************/     /*      program code        */     /****************************/     .text :     {         . = align(4);         *(.text)           /* .text sections (code) */         *(.text*)          /* .text* sections (code) */         *(.glue_7)         /* glue arm thumb code */         *(.glue_7t)        /* glue thumb arm code */         *(.eh_frame)           /* note: function ‘.text.reset_handler’ 1 of *(.text*) sections,      */         /* such gets linked output .text section somewhere here.          */         /* can verify exact spot reset_handler section positioned,  */         /* examining second entry of vector table.                                 */         /* test has given following results:         /*    flash (rx) : origin = 0x0800 0000    ==>  reset_handler = 0x0800 1c91        */         /*    flash (rx) : origin = 0x0020 0000    ==>  reset_handler = 0x0020 1cb9        */         /*         /* in both cases, reset_handler section ends few hundred bytes after  */         /* vector table in flash. in first case, “reset_handler” symbol points */         /* reset-code through axim-interface, whereas in latter case points  */         /* reset-code through itcm-interface.                                   */           keep (*(.init))         keep (*(.fini))          . = align(4);         _etext = .;        /* define global symbol @ end of code */      } >flash 

the linkerscript defines e_text global symbol represents address program code in flash ends.

constant data

the read-only data ends in flash memory (it makes no sense put in ram, volatile). linkerscript defines .rodata section should in flash:

    /****************************/     /*      constant data       */     /****************************/     .rodata :     {         . = align(4);         *(.rodata)         /* .rodata sections (constants, strings, etc.) */         *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */         . = align(4);     } >flash 

mysterious sections in flash

after defining constant read-only data should go, linkerscript defines few 'mysterious' sections should end in flash well:

    .arm.extab :     {         *(.arm.extab* .gnu.linkonce.armextab.*)     } >flash     .arm :     {         __exidx_start = .;         *(.arm.exidx*)         __exidx_end = .;     } >flash     .preinit_array :     {         provide_hidden (__preinit_array_start = .);         keep (*(.preinit_array*))         provide_hidden (__preinit_array_end = .);     } >flash     .init_array :     {         provide_hidden (__init_array_start = .);         keep (*(sort(.init_array.*)))         keep (*(.init_array*))         provide_hidden (__init_array_end = .);     } >flash     .fini_array :     {         provide_hidden (__fini_array_start = .);         keep (*(sort(.fini_array.*)))         keep (*(.fini_array*))         provide_hidden (__fini_array_end = .);     } >flash 

i have no idea sections are. let first question. these sections, , in object files show up? know, linkerscript needs link object files. have no idea in object files these mysterious sections exist:

  • .arm.extab
  • .arm
  • .preinit_array
  • .init_array
  • .fini_array

this end of allocations flash memory. linkerscript continues defining sections end in ram.

sections in ram

the .data , .bss sections clear me. no questions this.

    /****************************/     /*    initialized data      */     /****************************/     _sidata = loadaddr(.data);     .data :     {         . = align(4);         _sdata = .;        /* create global symbol @ data start */         *(.data)           /* .data sections */         *(.data*)          /* .data* sections */          . = align(4);         _edata = .;        /* define global symbol @ data end */      } >ram at> flash       /****************************/     /*    uninitialized data    */     /****************************/     . = align(4);     .bss :     {         _sbss = .;         /* define global symbol @ bss start */         __bss_start__ = _sbss;         *(.bss)         *(.bss*)         *(common)          . = align(4);         _ebss = .;         /* define global symbol @ bss end */         __bss_end__ = _ebss;      } >ram 

the linkerscript defines ._user_heap_stack section:

    /****************************/     /* user_heap_stack section  */     /****************************/     /* user_heap_stack section, used check there enough ram left */     ._user_heap_stack :     {         . = align(8);         provide ( end = . );         provide ( _end = . );         . = . + _min_heap_size;         . = . + _min_stack_size;         . = align(8);     } >ram 

apparently section not used immediately. defined check if ram has still enough space stack , heap. linker error thrown when not case (the . exceeds top ram address).

the end of linkerscript

this how linkerscript ends. , honestly, have no idea does. second question: following mean?

    /* remove information standard libraries */     /discard/ :     {         libc.a ( * )         libm.a ( * )         libgcc.a ( * )     }      .arm.attributes 0 : { *(.arm.attributes) } } /* end of linkerscript */ 

  1. .arm.extab , .arm.exidx related unwinding. can find more information here http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/index.html. don't need them if don't care unwinding (unwinding useful c++ exception , debugging).

  2. these symbols related c / c++ constructor , destructor startup , tear down code called before / after main(). sections named .init, .ctors, .preinit_array, , .init_array initialization of c/c++ objects, , sections .fini, .fini_array, , .dtors tear down. start , end symbols define beginning , end of code sections related such operations , might referenced other parts of runtime support code.

the .preinit_array , .init_array sections contain arrays of pointers functions called on initialization. .fini_array array of functions called on destruction. presumably start , end labels used walk these lists.

  1. heap: not really, part permits reserve space heap , space stack. rises error if sum of reserved areas goes outside ram boundaries. example:

    _min_heap_size = 0; /* required amount of heap / _min_stack_size = 0x400; / required amount of stack */

    ._user_heap_stack : { . = align(4); provide ( end = . ); provide ( _end = . ); . = . + _min_heap_size; . = . + _min_stack_size; . = align(4); } >ram

  2. to link libraries prefer different notation, example bare-metal no rtos c++ project: group(libgcc.a libc_nano.a libstdc++_nano.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -