Initialization at system startup
In Standard C, all static variables—variables that are allocated at a fixed memory address—must be initialized by the runtime system to a known value at application startup. This value is either an explicit value assigned to the variable, or if no value is given, it is cleared to zero. In the compiler, there are exceptions to this rule, for example, variables declared __no_init, which are not initialized at all.
The compiler generates a specific type of section for each type of variable initialization:
Categories of declared data | Source | Section type | Section name | Section content |
|---|---|---|---|---|
Zero-initialized data | int i; | Read/write data, zero-init |
| None |
Zero-initialized data | int i = 0; | Read/write data, zero-init |
| None |
Initialized data (non-zero) | int i = 6; | Read/write data |
| The initializer |
Non-initialized data | __no_init int i; | Read/write data, zero-init |
| None |
Constants | const int i = 6; | Read-only data |
| The constant |
Code | __ramfunc void myfunc() {} | Read/write code |
| The code |
For information about all supported sections, see Section reference.
The initialization process
Initialization of data is handled by ILINK and the system startup code in conjunction.
To configure the initialization of variables, you must consider these issues:
Sections that should be zero-initialized, or not initialized at all (
__no_init) are handled automatically by ILINK.Sections that should be initialized, except for zero-initialized sections, should be listed in an
initializedirective.Normally during linking, a section that should be initialized is split into two sections, where the original initialized section will keep the name. The contents are placed in the new initializer section, which will get the original name suffixed with
_init. The initializers should be placed in ROM and the initialized sections in RAM, by means of placement directives. The most common example is the.datasection which the linker splits into.dataand.data_init.Sections that contains constants should not be initialized—they should only be placed in flash/ROM.
In the linker configuration file, it can look like this:
/* Handle initialization */
initialize by copy { readwrite }; /* Initialize RW sections */
/* Place startup code at a fixed address */
place at start of ROM { readonly code
object cstartup.o };
/* Place code and data */
place in ROM { readonly }; /* Place constants and initializers in
ROM: .rodata and .data_init */
place in RAM { readwrite, /* Place .data, .bss, and .noinit */
block STACK }; /* and STACK */Note
When compressed initializers are used (see initialize directive), the contents sections (that is, sections with the _init suffix) are not listed as separate sections in the map file. Instead, they are combined into aggregates of “initializer bytes”. You can place the contents sections the usual way in the linker configuration file, however, this affects the placement—and possibly the number—of the “initializer bytes” aggregates.
For more information about and examples of how to configure the initialization, see Linking considerations.
C++ dynamic initialization
The compiler places subroutine pointers for performing C++ dynamic initialization into sections of the ELF section types SHT_PREINIT_ARRAY and SHT_INIT_ARRAY. By default, the linker will place these into a linker-created block, ensuring that all sections of the section type SHT_PREINIT_ARRAY are placed before those of the type SHT_INIT_ARRAY. If any such sections were included, code to call the routines will also be included.
The linker-created blocks are only generated if the linker configuration does not contain section selector patterns for the preinit_array and init_array section types. The effect of the linker-created blocks will be very similar to what happens if the linker configuration file contains this:
define block SHT$$PREINIT_ARRAY { preinit_array };
define block SHT$$INIT_ARRAY { init_array };
define block CPP_INIT with fixed order { block SHT$$PREINIT_ARRAY,
block SHT$$INIT_ARRAY };If you put this into your linker configuration file, you must also mention the CPP_INIT block in one of the section placement directives. If you wish to select where the linker-created block is placed, you can use a section selector with the name ".init_array".
See also section-selectors.