mik32-runtime 0.4.0

Minimal Rust runtime for the MIK32 Amur microcontroller
Documentation
SECTIONS
{
  /* Reset/startup code executes directly from EEPROM or SPIFI. */
  .startup ORIGIN(REGION_TEXT) :
  {
    KEEP(*(.startup .startup.*));
  } > REGION_TEXT

  /* Latency-sensitive code is loaded from REGION_TEXT and run from SRAM. */
  .ram_text : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__RAM_TEXT_START__ = .);
    *(.small_ram_text .small_ram_text.*);

    . = ORIGIN(REGION_RAM) + 0xC0;
    PROVIDE(__TRAP_TEXT_START__ = .);
    KEEP(*(.trap_text .trap_text.*));

    *(.ram_text .ram_text.*);
    . = ALIGN(4);
    PROVIDE(__RAM_TEXT_END__ = .);
  } > REGION_RAM AT > REGION_TEXT

  __RAM_TEXT_IMAGE_START__ = LOADADDR(.ram_text);
  __RAM_TEXT_IMAGE_END__ = LOADADDR(.ram_text) + SIZEOF(.ram_text);

  .text : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__TEXT_START__ = .);
    *(.text.SmallSystemInit);
    *(.text .text.*);
    *(.gnu.linkonce.t.*);
    *(.rodata .rodata.*);
    *(.gnu.linkonce.r.*);
    . = ALIGN(4);
    PROVIDE(__TEXT_END__ = .);
  } > REGION_TEXT

  .tdata : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(_tls_data = .);
    PROVIDE(_tdata_start = .);
    *(.tdata .tdata.*);
    *(.gnu.linkonce.td.*);
    . = ALIGN(4);
    PROVIDE(_tdata_end = .);
  } > REGION_RAM AT > REGION_TEXT

  .tbss (NOLOAD) : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(_tbss_start = .);
    *(.tbss .tbss.*);
    *(.gnu.linkonce.tb.*);
    . = ALIGN(4);
    PROVIDE(_tbss_end = .);
  } > REGION_RAM

  __TDATA_IMAGE_START__ = LOADADDR(.tdata);
  __TDATA_IMAGE_END__ = LOADADDR(.tdata) + SIZEOF(.tdata);

  .data : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__DATA_START__ = .);
    *(.data .data.*);
    *(.gnu.linkonce.d.*);
    . = ALIGN(4);
    PROVIDE(__DATA_END__ = .);
  } > REGION_RAM AT > REGION_TEXT

  .sdata : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__SDATA_START__ = .);
    *(.sdata .sdata.* .sdata2 .sdata2.*);
    *(.gnu.linkonce.s.*);
    . = ALIGN(4);
  } > REGION_RAM AT > REGION_TEXT

  .srodata : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__SRODATA_START__ = .);
    *(.srodata .srodata.*);
    . = ALIGN(4);
  } > REGION_RAM AT > REGION_TEXT

  __DATA_IMAGE_START__ = LOADADDR(.data);
  __DATA_IMAGE_END__ = LOADADDR(.srodata) + SIZEOF(.srodata);

  .sbss (NOLOAD) : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__SBSS_START__ = .);
    *(.sbss .sbss.*);
    *(.gnu.linkonce.sb.*);
    *(.scommon);
    . = ALIGN(4);
    PROVIDE(__SBSS_END__ = .);
  } > REGION_RAM

  .bss (NOLOAD) : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__BSS_START__ = .);
    *(.bss .bss.*);
    *(.gnu.linkonce.b.*);
    *(COMMON);
    . = ALIGN(4);
    PROVIDE(__BSS_END__ = .);
  } > REGION_RAM

  .uninit (NOLOAD) : ALIGN(SECTION_ALIGNMENT)
  {
    PROVIDE(__UNINIT_START__ = .);
    *(.uninit .uninit.*);
    . = ALIGN(4);
    PROVIDE(__UNINIT_END__ = .);
  } > REGION_RAM

  __global_pointer$ = MIN(
    __SDATA_START__ + 2016,
    MAX(__DATA_START__ + 2016, __BSS_END__ - 2016)
  );

  PROVIDE(_end = .);
  PROVIDE(__end = .);
  PROVIDE(end = .);

  .stack ORIGIN(REGION_RAM) + LENGTH(REGION_RAM) - __stack_size (NOLOAD) : ALIGN(16)
  {
    PROVIDE(_heap_end = .);
    PROVIDE(__STACK_START__ = .);
    . += __stack_size;
    PROVIDE(__C_STACK_TOP__ = .);
    PROVIDE(__STACK_END__ = .);
  } > REGION_RAM

  .got (INFO) :
  {
    KEEP(*(.got .got.*));
  }

  /DISCARD/ :
  {
    *(.eh_frame .eh_frame.*);
  }
}

ASSERT(__RAM_TEXT_START__ == ORIGIN(REGION_RAM), ".ram_text must start at beginning of RAM");
ASSERT(__TRAP_TEXT_START__ == ORIGIN(REGION_RAM) + 0xC0, "trap entry must be at RAM + 0xC0");
ASSERT(__RAM_TEXT_IMAGE_END__ <= ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "REGION_TEXT overflows");
ASSERT(__UNINIT_END__ <= __STACK_START__, "REGION_RAM overflows into stack");
ASSERT(__C_STACK_TOP__ == ORIGIN(REGION_RAM) + LENGTH(REGION_RAM), "stack top is not RAM end");
ASSERT(SIZEOF(.got) == 0, "dynamic relocations are not supported");