ROM to RAM Copying

In embedded programming, it is common to copy a portion of a program resident in ROM into RAM at runtime. For example, program variables cannot be accessed until they are copied to RAM.

To indicate data or code that is meant to be copied from ROM to RAM, the data or code is assigned two addresses. One address is its resident location in ROM (where it is downloaded). The other is its intended location in RAM (where it is later copied in C code).

Use the MEMORY segment to specify the intended RAM location, and the AT(address) parameter to specify the resident ROM address.

For example, you have a program and you want to copy all your initialized data into RAM at runtime. The following listing shows the LCF you use to set up for writing data to ROM.

Listing: LCF setup for ROM to RAM copy
MEMORY {
  .text (RWX) : ORIGIN = 0x8000, LENGTH = 0x0   # code (p:)
  .data (RW)  : ORIGIN = 0x3000, LENGTH = 0x0   # data (x:)-> RAM
}

SECTIONS{
  
    .main_application :
  {
     # .text sections

     *(.text)
     *(.rtlib.text)
     *(.fp_engine.txt)
     *(user.text)
  } > .text
 
   __ROM_Address = 0x2000
   .data : AT(__ROM_Address)  # ROM Address definition 
  {
     # .data sections
     F__Begin_Data = .;       # Start location for RAM (0x3000)
     *(.data)                 # Write data to the section (ROM)
     *(fp_state.data);
     *(rtlib.data);
     F__End_Data = .;         # Get end location for RAM
  
     # .bss sections
     * (rtlib.bss.lo)
     * (.bss)
     F__ROM_Address = __ROM_Address

} > .data
} 

To make the runtime copy from ROM to RAM, you need to know where the data starts in ROM ( __ROM_Address) and the size of the block in ROM you want to copy to RAM. The following listing shows an example to copy all variables in the data section from ROM to RAM in C code.

Listing: ROM to RAM copy from C after writing data flash
#include <stdio.h>
#include <string.h>

int GlobalFlash = 6;

// From linker command file
extern __Begin_Data, __ROMAddress, __End_Data;

void main( void )
{
   unsigned short a = 0, b = 0, c = 0;      
   unsigned long dataLen  = 0x0;
   unsigned short __myArray[] = { 0xdead, 0xbeef, 0xcafe };
  
   // Calculate the data length of the X: memory written to Flash
   dataLen = (unsigned long)&__End_Data -
   unsigned long)&__Begin_Data;  
  
   // Block move from ROM to RAM
   memcpy( (unsigned long *)&__Begin_Data,
  (const unsigned long *)&__ROMAddress,dataLen );

   a = GlobalFlash; 

   return;
 }