Ruffian Heng embedded: deeply dig the initialization function of IAR startup function process__ iar_data_init3 implementation

Hello, I'm ruffian Heng, a serious technical ruffian. What ruffian Heng shared with you today is the segment initialization function in the IAR startup function process__ iar_data_init3 implementation.

This article is IAR startup function process and its _low_level_init design impact on function redirection In the last article, we found the standard startup function in the IAR software installation directory__ iar_program_start() related source files, and analyzed__ iar_ program_ All actions in the start() function. We know that the one responsible for initializing the. data/.bss/.textrw section is__ iar_data_init3() function, but the specific implementation of this function is not described in detail. Today we will talk about this in detail__ iar_data_init3() function:

  • Note 1: before reading this article, you need to IAR link file (. icf) Know something.
  • Note 2: the IAR EWARM software version used in this article is v9.10.2.

1, Why do some segments need to be initialized?

  IAR link file (. icf) The first Section of this article lists all the system Section names defined in IAR project. Among them, the. data/.bss/.textrw Section needs to be initialized. Because these sections are linked in RAM and ram is powered on, their contents are random values, so a startup code is required to fill the ram area where the. data/.bss/.textrw Section is located with the corresponding initial value (the initial value comes from the Flash area where the program image file is downloaded), and then the application can run normally.

  • Note: in addition to. data/.bss/.textrw, some segments (. noinit/CSTACK/HEAP, etc.) are also linked in the RAM area, but these segments do not depend on the initial value, so initialization is not required.
.bss                 // Static / global variable (RAM) with initial value of 0
.data                // Global variable (RAM) with initial value of non-0
.data_init           // Initial value of. data section (Flash)
.textrw              // __ramfunc modified redirection function actual execution area (RAM)
.textrw_init         // Machine code storage area (Flash) of. textrw segment

2, General implementation of RW/ZI segment initialization

After compiling the link, the actual link address of the. data/.bss/.textrw section is determined (this means that the IAR linker freely assigns the specific link address by default, rather than the user indicates the specific link address in the link file). After we know the link addresses of these sections, we can complete the corresponding initialization (to put it bluntly, it is the copy of initial value data from Flash to RAM). The actual link address can be obtained through the interface provided by the IAR linker below. See the specific copy process Method of redirecting key functions to RAM for execution under IAR The code in the last section of this article.

  • Note: for the convenience of subsequent initialization, the IAR linker places all the global variables in the program next to a continuous RAM area (. data), and then all their initial values are placed next to each other one by one (. data_init, downloaded to a continuous Flash area); the processing of. textrw is also similar.
#pragma section = ".data"
#pragma section = ".data_init"
#pragma section = ".bss"
#pragma section = ".textrw"
#pragma section = ".textrw_init"

uint8_t *data_ram              = __section_begin(".data");
uint8_t *data_rom              = __section_begin(".data_init");
uint8_t *data_rom_end          = __section_end(".data_init");
uint8_t *bss_start             = __section_begin(".bss");
uint8_t *bss_end               = __section_end(".bss");
uint8_t *code_relocate_ram     = __section_begin(".textrw");
uint8_t *code_relocate_rom     = __section_begin(".textrw_init");
uint8_t *code_relocate_rom_end = __section_end(".textrw_init");

Although the general implementation of segment initialization is simple, it has a disadvantage that it can not automatically adapt to user-defined RW/ZI segments or multiple scattered RW/ZI segments, and the code implementation needs to be constantly adjusted according to the actual situation.

3, Implementation details of_iar_data_init3() function

After so much foreshadowing, it's time to watch the implementation of the IAR standard segment initialization function _iar_data_init3(). The source files related to this function are in the following path, and the core code is in the data_init.c file:

\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\init\data_init.c
\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\init\zero_init3.c  - deposit __iar_zero_init3 function
\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\init\copy_init3.c  - deposit __iar_copy_init3 function

There is a function called IAR_DATA_INIT in the data_init.c file. In fact, it is _iar_data_init3. Looking at the code in this function alone will make people a little confused. Because we use the interface and some special definitions in the IAR linker, we will explain it more clearly in combination with a specific application project.

// Macro definition in IAR directory \ arm\inc\c\DLib_Product.h
#define _DLIB_ELF_INIT_INTERFACE_VERSION 3

// Macro definition in IAR directory \ arm\src\lib\init\data_init.h
#define IAR_DATA_INIT _GLUE(__iar_data_init, _DLIB_ELF_INIT_INTERFACE_VERSION)

#pragma section = "Region$$Table" const TABLE_MEM
void IAR_DATA_INIT(void)
{
    FAddr TABLE_MEM const * pi = __section_begin("Region$$Table");
    table_ptr_t             pe = __section_end  ("Region$$Table");
    while (pi != pe)
    {
        init_fun_t * fun = FAddr_GetPtr(pi);
        ++pi;
        pi = fun(pi);
    }
}

Let's compile an SDK routine at random now (ruffian Heng selects \ SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\demo_apps\hello_world\cm7\iar, and switch to flexspi_nor_debug build, that is, the code RO segment is linked in the Flash area starting from 0x30000000 and the code RW segment is linked in the DTCM area starting from 0x20000000), and check its corresponding mapping file (. map) , some contents related to segment initialization are extracted as follows. The initialization work includes: clearing the ZI segment space with the starting address of 0x20000040 and the length of 0x4c bytes by using the _ iar_zero_init3 function, and copying the RW segment data of 0x40 bytes by using the iar_copy_init3 function (from 0x300060fc to 0x20000000):

*******************************************************************************
*** INIT TABLE
***

          Address      Size
          -------      ----
Zero (__iar_zero_init3)
    1 destination range, total size 0x4c:
          0x2000'0040  0x4c

Copy (__iar_copy_init3)
    1 source range, total size 0x40:
          0x3000'60fc  0x40
    1 destination range, total size 0x40:
          0x2000'0000  0x40

*******************************************************************************
*** ENTRY LIST
***

Entry                       Address   Size  Type      Object
 ----                       -------   ----  ----      ------
.iar.init_table$$Base   0x3000'63d4          --   Gb  - Linker created -
.iar.init_table$$Limit  0x3000'63f8          --   Gb  - Linker created -
Region$$Table$$Base     0x3000'63d4          --   Gb  - Linker created -
Region$$Table$$Limit    0x3000'63f8          --   Gb  - Linker created -
__iar_copy_init3        0x3000'630d   0x2c  Code  Gb  copy_init3.o [6]
__iar_zero_init3        0x3000'613d   0x3c  Code  Gb  zero_init3.o [6]

In the mapping file, we know the start and end addresses [0x300063d4 - 0x300063f8] of the Region$$Table region. Open the image file or find the contents of this region through online debugging, and you will find all the information required for segment initialization (operation function address, operation data length, operation source address and operation target address) All are recorded in it. It is particularly noted that the addresses related to the Flash area are stored in relative addresses:

  • Note: FAddr_GetPtr function is responsible for address translation. The value at 0x300063d4 address is 0xfffffd69, then 0x300063d4 + 0xfffffd69 = 0x1300613d, and the lower 32bit is the _iar_zero_init3 function address.

Now we have a good understanding of the code in the _iar_data_init3 function. It is to take out the information required for initialization from the Region$$Table area in order and complete the segment initialization one by one. The advantage of this implementation method is that it has strong expansibility. The IAR linker can freely expand the Region$$Table area according to the link of the actual application project The _iar_data_init3 function itself does not need to be modified.

So far, the segment initialization function _iar_data_init3 in the IAR startup function process has been introduced. Where are the applause~~~

Welcome to subscribe

The article will be published to me at the same time Blog Park home page,CSDN home page,Zhihu home page,WeChat official account On the platform.

Wechat search "ruffian Heng embedded" or scan the QR code below, you can see it for the first time on your mobile phone.

Added by Flying Sagittarius on Tue, 30 Nov 2021 19:31:52 +0200