ROM-RAM Copying

In embedded programming, it is common that data or code of a program residing in ROM gets copied into RAM at runtime.

To indicate such data or code, use the LCF to assign it two addresses:

For example, suppose you want to copy all initialized data into RAM at runtime. At runtime, the system loads the .main_data section containing the initialized data to RAM address 0x80000, but until runtime, this section remains in ROM. The following listing shows part of the corresponding LCF.

Listing: Partial LCF for ROM-to-RAM Copy
# ROM location: address 0x0
# RAM location: address 0x800000

# For clarity, no alignment directives in this listing

MEMORY {

  TEXT (RX) : ORIGIN = 0x0, LENGTH = 0

  DATA (RW) : ORIGIN = 0x800000, LENGTH = 0

}

SECTIONS{

  .main :

  {

    *(.text)

    *(.rodata)

  } > TEXT

# Locate initialized data in ROM area at end of .main.

  .main_data : AT( ADDR(.main) + SIZEOF(.main) )

  {

    *(.data)

    *(.sdata)

    *(.sbss)

  } > DATA

  .uninitialized_data:

  {

    *(SCOMMON)

    *(.bss)

    *(COMMON)

  } >> DATA

For program execution to copy the section from ROM to RAM, a copy table as shown in the following listing, must supply the information that the program needs at runtime. This copy table, which the symbol __S_romp identifies, contains a sequence of three word values per entry:

The last entry in this table must be all zeros: this is the reason for the three lines WRITEW(0) ; before the table closing brace character.

Listing: LCF Copy Table for Runtime ROM Copy
# Locate ROM copy table into ROM after initialized data
_romp_at = _main_ROM + SIZEOF(.main_data);

 .romp : AT (_romp_at)

 {

   __S_romp = _romp_at;

   WRITEW(_main_ROM);          #ROM start address

   WRITEW(ADDR(.main_data));   #RAM start address

   WRITEW(SIZEOF(.main_data)); #size

   WRITEW(0);

   WRITEW(0);

   WRITEW(0);

 }

 __SP_INIT = . + 0x4000;  # set stack to 16kb

 __heap_addr = __SP_INIT; # heap grows opposite stack direction

 __heap_size = 0x10000;   # set heap to 64kb

}                         # end SECTIONS segment

                          # end LCF