/* Memory layout for esp-open-rtos when using OTA second stage bootloader */
MEMORY
{
  dport0_0_seg :                      	org = 0x3FF00000, len = 0x10
  dram0_0_seg :                       	org = 0x3FFE8000, len = 0x14000
  iram1_0_seg :                       	org = 0x40100000, len = 0x08000
/* irom0 section, mapped from SPI flash
  - Origin is offset by 0x2010 to create spacer for second stage bootloader image,
    header.

  - Length is max 8Mbit of mappable flash, minus start offset
*/
  irom0_0_seg :                       	org = 0x40202010, len = (1M - 0x2010)
}

/* FreeRTOS memory management functions

   We link these directly to newlib functions (have to do it at link
   time as binary libraries use these symbols too.)
*/
pvPortMalloc = malloc;
vPortFree = free;

/* FreeRTOS lock functions.

   Rely on a patch to libc that produces weak linked versions of the
   below symbols. Currently treating locking primitives like universal
   global critical section rather than individual locks, but this seems
   OK from the use cases in newlib.
*/
_lock_acquire = vPortEnterCritical;
_lock_acquire_recursive = vPortEnterCritical;
_lock_try_acquire = vPortEnterCritical;
_lock_try_acquire_recursive = vPortEnterCritical;
_lock_release = vPortExitCritical;
_lock_release_recursive = vPortExitCritical;

/* SDK compatibility */
ets_printf = printf;

PHDRS
{
  dport0_0_phdr PT_LOAD;
  dram0_0_phdr PT_LOAD;
  dram0_0_bss_phdr PT_LOAD;
  iram1_0_phdr PT_LOAD;
  irom0_0_phdr PT_LOAD;
}


/*  Default entry point:  */
ENTRY(call_user_start)
PROVIDE(_memmap_vecbase_reset = 0x40000000);
/* Various memory-map dependent cache attribute settings: */
_memmap_cacheattr_wb_base = 0x00000110;
_memmap_cacheattr_wt_base = 0x00000110;
_memmap_cacheattr_bp_base = 0x00000220;
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
_memmap_cacheattr_wb_trapnull = 0x2222211F;
_memmap_cacheattr_wba_trapnull = 0x2222211F;
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
_memmap_cacheattr_wt_trapnull = 0x2222211F;
_memmap_cacheattr_bp_trapnull = 0x2222222F;
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
_memmap_cacheattr_wb_allvalid = 0x22222112;
_memmap_cacheattr_wt_allvalid = 0x22222112;
_memmap_cacheattr_bp_allvalid = 0x22222222;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);

SECTIONS
{

  .dport0.rodata : ALIGN(4)
  {
    _dport0_rodata_start = ABSOLUTE(.);
    *(.dport0.rodata)
    *(.dport.rodata)
    _dport0_rodata_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .dport0.literal : ALIGN(4)
  {
    _dport0_literal_start = ABSOLUTE(.);
    *(.dport0.literal)
    *(.dport.literal)
    _dport0_literal_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .dport0.data : ALIGN(4)
  {
    _dport0_data_start = ABSOLUTE(.);
    *(.dport0.data)
    *(.dport.data)
    _dport0_data_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .text : ALIGN(4) /* IRAM */
  {
    _stext = .;
    _text_start = ABSOLUTE(.);
    . = ALIGN (16);
    *(.vecbase.text)
    *(.entry.text)
    *(.init.literal)
    *(.init)
    /* esp-open-rtos compiled source files use the .iram1.* section names for IRAM
       functions, etc. */
    *(.iram1.*)
    /* SDK libraries expect their .text sections to link to iram, not irom */
    *sdklib*:*(.literal .text .literal.* .text.*)
    /* libgcc integer functions also need to be in .text, as some are called before
       flash is mapped (also performance)
    */
    *libgcc.a:*i3.o(.literal .text .literal.* .text.*)

    /* libc also in IRAM */
    *libc.a:*malloc.o(.literal .text .literal.* .text.*)
    *libc.a:*mallocr.o(.literal .text .literal.* .text.*)
    *libc.a:*freer.o(.literal .text .literal.* .text.*)
    *libc.a:*memcpy.o(.literal .text .literal.* .text.*)
    *libc.a:*memset.o(.literal .text .literal.* .text.*)
    *libc.a:*memcmp.o(.literal .text .literal.* .text.*)
    *libc.a:*memmove.o(.literal .text .literal.* .text.*)
    *libc.a:*rand.o(.literal .text .literal.* .text.*)
    *libc.a:*bzero.o(.literal .text .literal.* .text.*)
    *libc.a:*lock.o(.literal .text .literal.* .text.*)

    *libc.a:*printf.o(.literal .text .literal.* .text.*)
    *libc.a:*findfp.o(.literal .text .literal.* .text.*)
    *libc.a:*fputwc.o(.literal .text .literal.* .text.*)

    /* xthal_set_intset() called from PendSV in NMI context */
    *libhal.a:*set_intset.o(.literal .text .literal.* .text.*)

    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
    *(.fini.literal)
    *(.fini)
    *(.gnu.version)
    _text_end = ABSOLUTE(.);
    _etext = .;
  } >iram1_0_seg :iram1_0_phdr

  .data : ALIGN(4)
  {
    _data_start = ABSOLUTE(.);
    *(.data)
    *(.data.*)
    *(.gnu.linkonce.d.*)
    *(.data1)
    *(.sdata)
    *(.sdata.*)
    *(.gnu.linkonce.s.*)
    *(.sdata2)
    *(.sdata2.*)
    *(.gnu.linkonce.s2.*)
    *(.jcr)
    _data_end = ABSOLUTE(.);
  } >dram0_0_seg :dram0_0_phdr

  /* rodata in DRAM

     cherry-picked compilation units that need rodata
     to be in DRAM - anything that may be run while
     SPI flash is unmapped (ie IRAM functions that are
     called from interrupt context or spi flash management
     functions) need their compilation units listed here.

     If you have constant data that is performance-critical,
     list the compilation unit(s) here as well.
  */
  .rodata : ALIGN(4)
  {
    _rodata_start = ABSOLUTE(.);

    /* Store all of core, libc, freertos .rodata in RAM by default
       (some parts are necessary, some parts for performance reasons.)
    */
    *core.a:*(.rodata.* .rodata) *libc.a:*.o(.rodata.* .rodata)
    *freertos.a:*(.rodata.* .rodata)

    /* spi flash management rodata needs to be accessed
       while flash is unmapped. */
    *libmain.a:spi_flash.o(.rodata.* .rodata)

    /* libpp wdev.o has the NMI handler (sdk_wDev_ProcessFiq)
       which runs at all times, flash mapped or not. */
    *libpp.a:wdev.o(.rodata.* .rodata)

    _rodata_end = ABSOLUTE(.);
  } > dram0_0_seg :dram0_0_phdr

  .bss ALIGN(8) (NOLOAD) : ALIGN(4)
  {
    . = ALIGN (8);
    _bss_start = ABSOLUTE(.);
    *(.dynsbss)
    *(.sbss)
    *(.sbss.*)
    *(.gnu.linkonce.sb.*)
    *(.scommon)
    *(.sbss2)
    *(.sbss2.*)
    *(.gnu.linkonce.sb2.*)
    *(.dynbss)
    *(.bss)
    *(.bss.*)
    *(.gnu.linkonce.b.*)
    *(COMMON)
    . = ALIGN (8);
    _bss_end = ABSOLUTE(.);
    _heap_start = ABSOLUTE(.);
/*    _stack_sentry = ALIGN(0x8); */
  } >dram0_0_seg :dram0_0_bss_phdr
/* __stack = 0x3ffc8000; <-- this value seems a bit odd, stack on sdk_user_start is ~0x3ffffce9 */


   /* All data that goes to flash (IROM) ends up in this section */
  .irom0.text : ALIGN(4)
  {
    /*****************************
     * Actual irom0 text section *
     *****************************/

    _irom0_text_start = ABSOLUTE(.);
    /* esp-open-rtos compiled code goes into IROM by default
       (except for libgcc which is matched above.)

       We also link .rodata here in the hope that data is stored near
       its code on the flash (in practice this doesn't quite happen. :/)
    */
    *(.literal .text .literal.* .text.* .rodata .rodata.*)
    /* Anything explicitly marked as "irom" or "irom0" should go here */
    *(.irom.* .irom.*.* .irom0.*)
    _irom0_text_end = ABSOLUTE(.);

    /**************************************************************
      C++ constructor and destructor tables, properly ordered:
     **************************************************************/
    __init_array_start = ABSOLUTE(.);
    KEEP (*crtbegin.o(.ctors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    __init_array_end = ABSOLUTE(.);
    KEEP (*crtbegin.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))

    /***********************************
       C++ exception handlers table:  *
     **********************************/
    __XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
    *(.xt_except_desc)
    *(.gnu.linkonce.h.*)
    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
    *(.xt_except_desc_end)

    /***********************************
     Additional .rodata special sections
     stored in flash
     ************************************/
    . = ALIGN(4);
    *(.gnu.linkonce.r.*)
    __XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
    *(.xt_except_table)
    *(.gcc_except_table)
    *(.gnu.linkonce.e.*)
    *(.gnu.version_r)
    *(.eh_frame)
    . = ALIGN(4);
    *(.dynamic)
    *(.gnu.version_d)
    . = ALIGN(4);       /* this table MUST be 4-byte aligned */
    _bss_table_start = ABSOLUTE(.);
    LONG(_bss_start)
    LONG(_bss_end)
    _bss_table_end = ABSOLUTE(.);
  } > irom0_0_seg :irom0_0_phdr

  .lit4 : ALIGN(4)
  {
    _lit4_start = ABSOLUTE(.);
    *(*.lit4)
    *(.lit4.*)
    *(.gnu.linkonce.lit4.*)
    _lit4_end = ABSOLUTE(.);
  } >iram1_0_seg :iram1_0_phdr
}
