/* Entry Point of program, interrupt vector table in this case.*/
/* IVT: data structure that associates list of interrupt handlers with
 * a list of interrupt requests in a table of interrupt vectors.
 */
ENTRY( InterruptVector )

/*
 * Memory Layout:
 * Flash(read execute): 
 * Ram(read write execute)
 */
MEMORY
{
 FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
 RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K
}


SECTIONS
{
    /*
     * Initialization section:
     * handles startup initialization routines stored in flash.
     */
    .init :
    {
      _sinit = .;
      . = ALIGN(4);
      KEEP(*(SORT_NONE(.init)))
      . = ALIGN(4);
      _einit = .;
    } >FLASH AT>FLASH

    /*
     * Text Section:
     * Contains executable code and read-only data(rodata)
     * Stored in flash. 
     */
    .text :
    {
      . = ALIGN(4);
      *(.text)
      *(.text.*)
      *(.rodata)
      *(.rodata*)
      *(.gnu.linkonce.t.*)
    
      /* Include additional object files. */
      /* *(EXTERN(*)) /* Link against external symbols */

      . = ALIGN(4);
    } >FLASH AT>FLASH

    /*
     * Finalization Section:
     * Contains finalization routines, executed before exiting the program.
     */
    .fini :
    {
      KEEP(*(SORT_NONE(.fini)))
      . = ALIGN(4);
    } >FLASH AT>FLASH

    /*PROVODE: defines a symbol only if it is not already defined elsewhere.*/
    PROVIDE( _etext = . );
    PROVIDE( _eitcm = . );

    /*
     * The preinit_array and init_array handle static/global constructors and 
     * initalizers.
     */
    .preinit_array :
    {
      PROVIDE_HIDDEN (__preinit_array_start = .);
      KEEP (*(.preinit_array))
      PROVIDE_HIDDEN (__preinit_array_end = .);
    } >FLASH AT>FLASH
    .init_array :
    {
      PROVIDE_HIDDEN (__init_array_start = .);
      KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
      KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
      PROVIDE_HIDDEN (__init_array_end = .);
    } >FLASH AT>FLASH
    .fini_array :
    {
      PROVIDE_HIDDEN (__fini_array_start = .);
      KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
      KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
      PROVIDE_HIDDEN (__fini_array_end = .);
    } >FLASH AT>FLASH

    /* Constructors Section: needed for C++ */
    .ctors :
    {
      KEEP (*crtbegin.o(.ctors))
      KEEP (*crtbegin?.o(.ctors))
      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
      KEEP (*(SORT(.ctors.*)))
      KEEP (*(.ctors))
    } >FLASH AT>FLASH

    /* Destructors Section: needed for C++ */
    .dtors :
    {
      KEEP (*crtbegin.o(.dtors))
      KEEP (*crtbegin?.o(.dtors))
      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
      KEEP (*(SORT(.dtors.*)))
      KEEP (*(.dtors))
    } >FLASH AT>FLASH


    /* Likely for data alignment.*/
    .dalign :
    {
      . = ALIGN(4);
      PROVIDE(_data_vma = .);
    } >RAM AT>FLASH

    /* Likely for  dynamic loader alignment.*/
    .dlalign :
    {
      . = ALIGN(4);
      PROVIDE(_data_lma = .);
    } >FLASH AT>FLASH

    /*
     * Data section: Initialized Variables
     * contains initialized variables copied from flash to ram at startup.
     * `_sdata` and `_edata` mark the start and end of the `.data` section.
     */
    .data :
    {
      . = ALIGN(4);
      __global_pointer$ = . + 0x3fc;
      *(.gnu.linkonce.r.*)
      *(.data .data.*)
      *(.gnu.linkonce.d.*)
      . = ALIGN(8);
      *(.sdata .sdata.*)
      *(.sdata2*)
      *(.gnu.linkonce.s.*)
      . = ALIGN(8);
      *(.srodata.cst16)
      *(.srodata.cst8)
      *(.srodata.cst4)
      *(.srodata.cst2)
      *(.srodata .srodata.*)

      /* Trying to include datasections for external object files.*/
      /* 
       * *(.data)
       * *(.data.*)
       */

      . = ALIGN(4);
      PROVIDE( _edata = .);
    } >RAM AT>FLASH

    /* BSS Section: Contains uninitialized variables.
     * Holds uninited global/static vars. The runtime must zero out this
     * section before main function.
     */
    .bss :
    {
      . = ALIGN(4);
      PROVIDE( _sbss = .);
      *(.sbss*)
      *(.gnu.linkonce.sb.*)
      *(.bss*)
      *(.gnu.linkonce.b.*)
      *(COMMON*)
      . = ALIGN(4);
      PROVIDE( _ebss = .);
    } >RAM AT>FLASH
    PROVIDE( _end = _ebss);
 PROVIDE( end = . );
 PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM));
    /DISCARD/ : {
      *(.note .note.*)
      *(.eh_frame .eh_frame.*)
      *(.comment .comment.*)
      *(.ARM.extab* .gnu.linkonce.armextab.*)
      *(.ARM.exidx*)
    }
}
