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.
# 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 such as 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.
# 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