There are a few rules you have to follow with most embedded platforms.
The reset handler and vector table must be at a defined location specified by the hardware.
You can't have different load and execution address regions (LR/ER) for the reset boot region. The linker inserts a scripts that copies data from the load region to the execution region if these do not overlap. Such as with region RW_IRAM1 below. Since you can't write to flash in normal conditions, this fails.
You can't change the memory regions after compilations if it was not compiled to be memory location independent. The code might contain absolute jumps.
Eg: jump to 0x0800400 for foo(). Or read 0x0802FFE for char x.
Example of valid scatter file.
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00001000 { ; load address = execution address
*.o (RESET, +First) ; boot code
*(InRoot$$Sections) ; linker loader parts, initializes RW_IRAM1
.ANY (+RO) ; your code
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
You can add extra load regions (LR), for external memory. If the loader application sets up the interface.
You can add extra regions, for things like non volatile memory emulation. To have it pre-loaded or skipped during programming.
Here you can find everything for the linker. Which has a section of scatter loading.