0
votes

I have generated *.o files by compiling an example project with Keil, then I edited the *sct file with the address I wanted instead of the default 0x08000000 and generated *.elf with the specified loading and executing addresses.

I have loaded the *.elf file into the flash memory and it worked. It was downloaded at the specified address, however when I checked the memory I've found that the data have changed, which is wired since I didn't touch the *.o files and only called the linker each time.

My question is, why with the same *.o, just by changing the addresses, my data is affected too?

1

1 Answers

1
votes

There are a few rules you have to follow with most embedded platforms.

  1. The reset handler and vector table must be at a defined location specified by the hardware.

  2. 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.

  3. 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.