} > REGION_DATA data_size = SIZEOF(.data); data_load_start = LOADADDR(.data); .bss : { *(.bss) } > REGION_BSS } Now we need three different 'linkcmds.memory' files to define memory regions and alias names. The content of 'linkcmds.memory' for the three variants 'A', 'B' and 'C': 'A' Here everything goes into the 'RAM'. MEMORY { RAM : ORIGIN = 0, LENGTH = 4M } REGION_ALIAS("REGION_TEXT", RAM); REGION_ALIAS("REGION_RODATA", RAM); REGION_ALIAS("REGION_DATA", RAM); REGION_ALIAS("REGION_BSS", RAM); 'B' Program code and read-only data go into the 'ROM'. Read-write data goes into the 'RAM'. An image of the initialized data is loaded into the 'ROM' and will be copied during system start into the 'RAM'. MEMORY { ROM : ORIGIN = 0, LENGTH = 3M RAM : ORIGIN = 0x10000000, LENGTH = 1M } REGION_ALIAS("REGION_TEXT", ROM); REGION_ALIAS("REGION_RODATA", ROM); REGION_ALIAS("REGION_DATA", RAM); REGION_ALIAS("REGION_BSS", RAM); 'C' Program code goes into the 'ROM'. Read-only data goes into the 'ROM2'. Read-write data goes into the 'RAM'. An image of the initialized data is loaded into the 'ROM2' and will be copied during system start into the 'RAM'. MEMORY { ROM : ORIGIN = 0, LENGTH = 2M ROM2 : ORIGIN = 0x10000000, LENGTH = 1M RAM : ORIGIN = 0x20000000, LENGTH = 1M } REGION_ALIAS("REGION_TEXT", ROM); REGION_ALIAS("REGION_RODATA", ROM2); REGION_ALIAS("REGION_DATA", RAM); REGION_ALIAS("REGION_BSS", RAM); It is possible to write a common system initialization routine to copy the '.data' section from 'ROM' or 'ROM2' into the 'RAM' if necessary: #include extern char data_start []; extern char data_size []; extern char data_load_start []; void copy_data(void) { if (data_start != data_load_start) { memcpy(data_start, data_load_start, (size_t) data_size); } }