Variable Initialization in IAR

Those who learn C language know that initialized global variables are stored in the data segment by default, while uninitialized or initialized to 0 are stored in the bss segment. Software engineers generally do not feel these parameter initializations, but the underlying principles need to be studied. This article introduces the knowledge of variable initialization under IAR.

Initialization of Global and Static Variables

The following introduces the built-in startup code based on IAR. If your build project uses custom startup code, it depends on your code implementation.

1、Global variables and static variables with an initial value of 0:

Variable Initialization in IAR

2、Global variables and static variables with a non-zero initial value, the initial value is copied from ROM to RAM:

Variable Initialization in IAR

IAR’s Initialization Strategy

initialize by copy (initialization of 0 and non-0 variables)

IAR uses initialize by copy to implement the initialization actions mentioned at the beginning of the article. Add the following command in the ICF file, and the Linker will automatically add the corresponding initializers and automatically complete the initialization operation in the startup code.

initialize by copy { readwrite section .xxx_section };

The INIT TABLE in the map file will list the information needed for initialization, including:

1. Variables with an initial value of 0 are initialized by __iar_zero_init3(); 2. Variables with a non-zero initial value are initialized by __iar_copy_init3(); Initializer bytes are stored in ROM, and __iar_copy_init3() will copy the Initializer bytes from ROM to RAM, completing the initialization of non-zero variables.Variable Initialization in IARVariable Initialization in IAR

Note:

The initialize by copy command needs to call __iar_program_start() in the startup code. Both the __iar_zero_init3 function and the __iar_copy_init3 function are called by __iar_program_start. If not called, the linker will prompt an error similar to the one below.

Variable Initialization in IAR

initialize manually (initialization of non-0 variables)

For certain parameters, you may not want IAR to initialize them. For non-zero variables, you can use initialize manually to manually initialize variables with a non-zero initial value (the code uses __iar_program_start for initialization, and you can also use the initialize manually initialization strategy for manual initialization). As shown below: manually initialize the .data section:

1. .data contains variables with a non-zero initial value;2. .data_init (section automatically created by IAR) contains Initializer bytes with a non-zero initial value;

define block MY_DATA { section .data };define block MY_DATA_INIT { section .data_init };initialize manually { section .data };place in IRAM_region  { block MY_DATA };place in IROM_region  { block MY_DATA_INIT };

Then add the manual initialization code for the .data section in the code. The #pragma section is used to define the corresponding section name, and the section operators __section_begin, __section_end, and section_size are used to obtain the start address, end address, and size of the corresponding section respectively.

#pragma section = "MY_DATA"#pragma section = "MY_DATA_INIT"static void MyDataSectionInit(void){    char * from = __section_begin("MY_DATA_INIT");    char * to = __section_begin("MY_DATA");    memcpy(to, from, __section_size("MY_DATA"));}int main(void){    MyDataSectionInit();    …  }

In the MAP file, .data is located in MY_DATA, placed in RAM, and the corresponding .data_init (Initializer bytes) is located in MY_DATA_INIT, placed in ROM.

do not initialize (initialization of 0 variables)

For certain parameters, you may not want IAR to initialize them. For variables with an initial value of 0, you can use the do not initialize initialization strategy to manually initialize variables with an initial value of 0 (of course, the code uses __iar_program_start for initialization, and you can also use the do not initialize initialization strategy for manual initialization of global and static variables with an initial value of 0).

As shown below, manually initialize the .bss section: .bss contains global and static variables with an initial value of 0.

define block MY_BSS { section .bss };  do not initialize { section .bss };  place in IRAM_region  { block MY_BSS };

Then you need to add the manual initialization code for the .bss section in the code. The #pragma section command is used to define the corresponding section name, and the section operators __section_begin, __section_end, and section_size can be used to obtain the start address, end address, and size of the corresponding section respectively.

#pragma section = "MY_BSS"static void MyBssSectionInit(void){    char * to = __section_begin("MY_BSS");    memset(to, 0, __section_size("MY_BSS")); }int main(void) {    MyBssSectionInit();    …  }

For static and global variables that use __no_init, the linker will default to placing them in the .noinit section. You can use the do not initialize command in the ICF file, and the corresponding code cannot initialize the .noinit section, so the contents of the .noinit section will not have any initialization operations during startup.

do not initialize  { section .noinit };

Notes:

In IAR, if a variable is placed in a defined section and explicitly initialized to 0 (int i = 0),

it is required to perform copy initialization for such variables by default, rather than zero initialization.

As shown below, the variable TaskLedRedCounter is placed in the user-defined MY_SECTION section and explicitly initialized to 0.

#pragma location = "MY_SECTION" static uint32_t TaskLedRedCounter = 0;

In the MAP file, the static variable TaskLedRedCounter’s Kind is inited, not uninit; and the INIT TABLE generates the corresponding Initializer bytes:

Variable Initialization in IAR

This is somewhat different from the usual handling of variables with an initial value of 0. Since the Kind of the corresponding variable is inited, it is necessary to use the initialize manually initialization strategy (just like manually initializing global and static variables with a non-zero initial value).

If you want to use the do not initialize initialization strategy for the variable above, you need to use the compiler option –do_explicit_zero_opt_in_named_sections.

Variable Initialization in IARVariable Initialization in IAR

Conclusion

This article mainly introduces the initialization strategies in IAR: initialize by copy, initialize manually, and do not initialize. Users can reasonably choose the initialization strategy according to their needs:

1. If a variable cannot be initialized during startup, use the do not initialize initialization strategy, and no initialization can be performed on the related variables in the code;

2. If the startup code uses __iar_program_start:

(1) If there are no special initialization requirements, use the initialize by copy initialization strategy

(2) If there are special initialization requirements, refer to the situation where the startup code does not use __iar_program_start.

3. If the startup code does not use __iar_program_start:

(1) For variables with a non-zero initial value, use initialize manually, and add the corresponding code to copy the Initializer bytes from ROM to the corresponding RAM area;

(2) Generally, for variables with an initial value of 0, use do not initialize, and add the corresponding code to write 0 to the related RAM area;

(3) If a variable is placed in a user-defined section and manually assigned an initial value of 0, it is required to perform copy initialization for such variables (using the initialize by copy initialization strategy); you can also use the compiler option –do_explicit_zero_opt_in_named_sections to achieve zero initialization (using the do not initialize initialization strategy).

Leave a Comment