I have a set of initialised data structures that are now located in external memory. The structures are each defined using __attribute__((section("menu_structures"))).
A linker scatter file is used to locate this section to external memory.
RW_RAM1 0x81000000 0x00100000 { menu.o(menu_structures) }
This compiles and links without errors, but the structure elements are all initialised to 0. I have tried setting the 'Options for target' for this memory area to NoInit, and also to not selected. Both ways seem to leave the structure contents at 0.
Originally the structures were all by default in internal ram, and they were correctly initialised with non-zero values.
Can anyone help me as to why the structures are no longer initialised properly when located in external memory?
You need to locate your data in a zero initialized section, then place that section is a UNINIT execution region in the scatter file. See your linker manual for details. Example:
#pragma arm section zidata = "non_init_2" __attribute__ ((zero_init)) static software_evt_std s_queue_software_event_std[MAX_SOFTWARE_EVENTS_STD] ; // ring buffer __attribute__ ((zero_init)) static int32u s_queue_software_event_std_rx ; // for consumer - software event task __attribute__ ((zero_init)) static int32u s_queue_software_event_std_tx ; // for producers - posting tasks/firmware __attribute__ ((zero_init)) static int32u s_queue_software_event_std_size ; // number of elements in the ring buffer __attribute__ ((zero_init)) static software_evt_str s_queue_software_event_str[MAX_SOFTWARE_EVENTS_STR] ; // ring buffer __attribute__ ((zero_init)) static int32u s_queue_software_event_str_rx ; // for consumer - software event task __attribute__ ((zero_init)) static int32u s_queue_software_event_str_tx ; // for producers - posting tasks/firmware __attribute__ ((zero_init)) static int32u s_queue_software_event_str_size ; // number of elements in the ring buffer __attribute__ ((zero_init)) static file_storage_medium s_file_storage_medium ; // where are software events stored // the software events buffer is located here to allow post-crash analysis. data remains in the buffer // as long as power supply is maintained. __attribute__ ((zero_init)) static int8s sp_event_buffer[SOFTWARE_EVENT_BUFFER_SIZE] ; #pragma arm section zidata
and then in the scatter file
SOFTWARE_EVENT_ZERO_INIT_DATA.o 0xA1FFEC00 UNINIT { SOFTWARE_EVENT.o (non_init_2) }
There may be other ways to achieve this, too.
I am not ure that I can place my structures into the initial zero initialised section, since my structures contains non-zero values. If I attempt to do this then the compiler gives an error "variable may not be initialised".
Has access to the external memory been initialized BEFORE _main is called? If it is no initialized until after, then what you are seeing is quite possible.
I have set up the external memory access using the Startup configuration wizard, and I have also checked the values created in the startup.s file.
I'm new to the ARM tool chain and stumbled across this thread since I'm also looking for a way to have variables which are located in an external RAM initialized automatically by the startup code.
Can anybody give me a pointer for the best way to enable access to external memory before the startup code sets up initialized variables?
I mean especially where to put the code to set up the external memory mapping (I'm using Cortex-M3). I'd prefer to put as few changes as possible to the startup module which comes with the tool chain in order to keep a clean upgrade path for these files.
For the ARM chips that has support for external memory, the Keil startup files normally already have code to initialize the memory controllers.
I also want to know how to initialize of structures in external memory. Could you advise me more detail info about the initialzation in startup file. As I know, startup file can configure EMI for external SRAM. But I don't know how to initialize the data.
read about scatter loading in the linker manual, focusing on the difference between ZI and RW data. Also read about "__main".
you need to enable the EMC (use the startup file wizard), select the back on which the memory is mounted, and configure the parameters according to the spec of your memory. then map data to the memory region allocated to the device. scatter loading will set the value to either 0 or a required value as uncompressed from the load region.
See here, too:
infocenter.arm.com/.../index.jsp
Hello Tapier,
We are happy with you. you took our advise and now look at the ARM documents. remember the API.
Always yo're freind.
Zeusti.
Of course I meant ABI.
But of course you did.
View all questions in Keil forum