Hi.
I hope this is the right place to ask to open this question.
I define an initialized variable in my C code, let's say:
...
int MyVariable = 0xDEADABBA;
Using a scatter file, I instruct the arm linker to locate my variable "MyVariable" at address 0x04020000 :
LR_RAM_1 RAM_1_START RAM_1_SIZE ; load region starts at 0x04020000
{ ; start of execution region descriptions
ER_SRAM8 RAM_1_START SRAM8_SIZE
{
* (+RW, +ZI) ; All RW sections and All ZI sections are placed consecutively into this region
}
....
I expect the __main() function to initialize "MyVariable" with value 0xDEADABBA at start time, before my application "main()" function is executed.
However, I can clearly see in my RTL simulation that, for some reasons, MyVariable is not initialized, as if the compiler/linker consider the execution region "ER_SRAM8" as being already initialized (basically as if it was a ROM memory).
How to instruct the ARM linker that any initialized variable placed in execution region "ER_SRAM8" must be initialzed by the __main() function at boot time since this correspond to a SRAM area which by definition does not contain any valid data at boot time ?
Thanks in advance for your answers.
ARM Linker, 5.03 [Build 24]
ARM C/C++ Compiler, 5.03 [Build 24]
Didier C.
I suspect your problem lies with having the LOAD location identical to the EXEC location (both being RAM_1_START).
This implies that whatever "loaded" the image had already put the correct value at the "execution" location, i.e. you are relying on a debugger to do the loading, or the RAM already having the correct value.
If you want __main() to do the work, then I believe the LOAD location must be different from the EXEC location (typically flash for LOAD and RAM for EXEC), i.e. there must be a reference copy of the value that can be copied to RAM during __main(), and your scatter file should look more like:
LOAD_FLASH FLASH_START FLASH_SIZE { EXEC_CODE +0 { * (+RO) } EXEC_RAM RAM_START RAM_SIZE { * (+RW, +ZI) } }
In addition, the compiler may well optimise away MyVariable if it is not referenced.
hth
Simon.
There is a useful summary of the behaviour here:
ARM Compiler armlink User Guide : 7.1.6 Scatter-loading images with a simple memory map
Best regards,
Hi Simon.
Thanks for your answers. I'll go through the user guide and come back with more details.
Best regards.
Actually I did not provide you the whole information regarding my scatter file.
My scatter file looks like this:
---------------------------------------------------------------------------------------------
#! armcc -E
#define ROM_START 0x03000000
#define ROM_SIZE 0x00060000
#define RAM_0_START 0x04000000
#define RAM_0_SIZE 0x00016000 ; 88 KB
#define SRAM0_START RAM_0_START
#define SRAM0_SIZE 0x00004000
#define SRAM1_START (SRAM0_START + SRAM0_SIZE)
#define SRAM1_SIZE 0x00004000
LR_ROM ROM_START ROM_SIZE ; load region starts at 0x03000000{ ; start of execution region descriptions ER_ROM_SEC ROM_SEC_START ROM_SEC_SIZE ; load address = execution address { startup.o (init_boot, +FIRST) ; * (+RO) ; all others RO sections (must include section with initial entry point)
LR_RAM_1 RAM_1_START RAM_1_SIZE ; load region starts at 0x04020000{ ; start of execution region descriptions ER_SRAM8 RAM_1_START SRAM8_SIZE { * (+RW, +ZI) ; All RW sections and All ZI sections are placed consecutively into this region }
--------------------------------------------------------------------------------------------------------------
This looks to me very close to the example you indicated me in ARM Compiler armlink User Guide : 7.1.6 Scatter-loading images with a simple memory map
Or am I missing something (by the way, sure I miss something since the results is not what I expect :-) ) ?
"MyVariable" is not removed by the compiler/linker because it is used in the rest of my code and I can clearly see its address in the .lst file created by the linker.
Thanks in advance for your answer and support.
Didier,
Your scatter file differs in that the load address and exec address of your RW are identical, whereas in the examples provided the load address of the RW is in flash/ROM and the exec address is in RAM. __main() only need care about the case where load != exec, otherwise it could assume that the associated data is already in the exec location as a result of the load operation (be that either via the debugger/programmer, or via an OS that loaded the ELF). For a microcontroller coming out of reset, the value of RAM is unknown, thus what is preloaded on the device (i.e. the load image) can only reside in non-volatile flash/ROM, and __main() will contain code to convert the load image into the exec image before running your code. Thus, your scatterfile should probably look more like:
LR_ROM ROM_START ROM_SIZE ; Initialisation values for all code and data held in ROM ER_ROM_SEC ROM_SEC_START ROM_SEC_SIZE ; Code and read-only data executes directly from ROM (LOAD == EXEC) { ; (assumes ROM_SEC_START == ROM_START) startup.o (init_boot, +FIRST) * (+RO) } ER_SRAM8 RAM_1_START SRAM8_SIZE ; RW and ZI need unpacking to RAM before execution (LOAD != EXEC) { * (+RW, +ZI) } }
Best regards
Simon,
Thanks for your answer which just helped me realize that the concepts of "Load Region" and "Execution Region" were not clear enough in my mind.
This answer my initial question.
Thanks a lot and best regards.
Hi Coulibaly,
I am having the same situation here. Can I know how to solve this case in your example?
Thanks :)