Abstract: This article introduces the image analysis tool of LiteOS Studio, which is a powerful tool to evaluate and optimize the RAM and ROM footprint of image files.
We all know that the embedded development board is limited by the cost, the chip RAM, Flash and other hardware resources, such as some low-cost development board only built-in 64KB ROM, 20KB RAM. Seemingly harmless changes to feature-rich programming can cause compiled images to swell beyond the resource limits of the development board. For the development board with relatively rich hardware resources, reasonable planning of mirror size will also improve performance. This article introduces LiteOS Studio’s image analysis tool, which is a great tool for evaluating and optimizing the RAM and ROM footprint of image files.
Preparing for development Environment
Earlier in the series, we learned how to install LiteOS Studio, how to create STM32F769IDISCOVERY and Qemu RealView-PBX-A9 projects. This time we take STM32F429IGTx development board as an example, the way to create projects is the same, development board to choose STM32F429IGTx. The mirror analysis feature is applicable to any LiteOS project, we are just using this development board as an example. After the project is created, execute compilation and output is as follows:
The output of the terminal console shows that the compilation is successful. The executable file huawei_liteos. elf corresponds to a text segment of 74774 bytes, a data segment of 1444 bytes, a BSS segment of 13080 bytes, and a dec segment of 89268bytes. What do these text, data, and BSS data represent? What’s the point? Let’s move on. We’ll explain more later.
LiteOS image analysis features
Click the Debug Tools button on the LiteOS Studio toolbar to open the Debug tool and select Image Analysis. This is the image analysis tool for LiteOS Studio. Fill in executable file path, Map file path, etc., as shown in the figure:
Click ok to open the image analysis window automatically. Contains four tabs, including memory area, details, file size, and module size. We demonstrate how to use it in turn.
- Memory area
The memory area page evaluates and analyzes the memory subdivision usage of LiteOS development board project. For the STM32F429IGTx development board, the displayed memory region contains FLASH, RAM, and CCMRAM, and the displayed information includes the name, start memory address, total size, free size, used size, and usage ratio of each memory region. In this memory area page, in addition to numerical display analysis, but also provides a pie chart to evaluate the use of each area, the remaining situation. As shown in the figure below, the total FLASH size is 1,024KB, and the total RAM size is 192Kb. The utilization rate of FLASH and RAM is relatively low, just over 7%. CCMRAM is not used, CCM (Core Coupled Memory) is full speed 64KB RAM dedicated to the STM32F4 kernel.
- The detailed information
Continue clicking on the Details TAB to open the image Analysis details page, which shows details of the memory segment contained in each memory region, section, and symbol contained in the memory segment. For example, FLASH contains. Isr_vector,. Text,. Rodata and other memory segments, which in turn contain program symbols assigned to them. Each line displays the Virtual Memory Address (VMA), Load Memory Address (LMA), and Memory segment/symbol size. Where, LMA represents the memory address loaded by the program; The VMA represents the memory address of the program when it runs. In the embedded system, the RAM memory space is limited. Generally, the program is put in FLASH, and the LMA address is the address in FLASH. When the program runs, it is loaded into THE RUNNING address VMA in RAM. Memory segments. Data and. Vector_ram are in this case. VMA and LMA addresses are different and appear in both FLASH and RAM.
In the use of details page, support sorting and search filter, support program symbols quickly jump to the source code line. We can intuitively evaluate the usage size of each memory segment and program symbol, and can quickly locate potentially optimized resource consumers. As shown in figure:
From the image analysis chart, it can be seen that the text and data segments are stored in Flash, while the data and BSS segments are stored in RAM. So how does linker know how to store the symbolic data of each segment in ROM and RAM? This is done by linking scripts.
Link scripts to Text, Data, and BSS sections
The link script contains rules that govern how the linker places functions and variables in ROM or RAM. The link script for the STM32F429IGTx project is located in targetsCloud_STm32f429IGTX_fireliteos.ld. We display the image analysis page and link script in columns at the same time. As shown in the figure below, the memory usage displayed on the image analysis page is consistent with that defined in the link script. The memory usage of the development board is visually displayed on the Image analysis page of LiteOS Studio.
Ccmram is not defined in the link script, and the used size is also 0 byte. For.data and.vector_ram, the link script uses the keyword RAM AT> FLASH to indicate that the loading address and the actual running address are in FLASH and RAM respectively.
Text is stored in Flash, using the keyword > Flash, where Flash is stored in MEMORY{…… }.
/* The startup code goes first into FLASH / .isr_vector : { . = ALIGN(4); KEEP((.isr_vector)) /* Startup code / . = ALIGN(4); } >FLASH / The program code and other data goes into FLASH / .text : { . = ALIGN(4); __text_start = .; (.text) / .text sections (code) / (.text) / .text sections (code) */ (.glue_7) / glue arm to thumb code */ (.glue_7t) / glue thumb to arm code */ *(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */ __text_end = _etext;
Copy the code
} >FLASH
Vector_ram and.data are stored in Flash storage and copied from Flash to RAM when the program is started. The keyword used is >RAM AT> FLASH, where RAM is defined in MEMORY{} above.
/* Initialized liteos vector sections goes into RAM, load LMA copy after code / .vector_ram : { . = ORIGIN(RAM); _s_liteos_vector = .; (.data.vector) / liteos vector in ram / _e_liteos_vector = .; } > RAM AT> FLASH / used by the startup to initialize data / _sidata = LOADADDR(.data); / Initialized data sections goes into RAM, load LMA copy after code / .data ALIGN(0x1000): { __ram_data_start = _sdata; . = ALIGN(4); _sdata = .; / create a global symbol at data start / (.data) / .data sections / (.data) / .data sections / KEEP(( SORT (.liteos.table.)));
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */ __ram_data_end = _edata;
Copy the code
} >RAM AT> FLASH
Link script fragment 3 below, which defines.bss,._user_heap_stack to occupy RAM storage. The keyword used is >RAM.
.bss : { /* This is used by the startup in order to initialize the .bss secion / _sbss = .; / define a global symbol at bss start */ bss_start = _sbss; __bss_start = _sbss; *(.bss) (.bss) *(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss;
__bss_end = _ebss;
Copy the code
} >RAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM
Now to summarize, it usually goes something like this:
- The Text segment
Text is stored in a read-only ROM memory area that contains vector tables, program code, and read-only constant data.
- The Data segment
Represents an initialized variable. Store in FLASH and RAM. The linker allocates the data segment to the Flash area and copies it from ROM to RAM at startup time. ROM is stored in a read-only copy, development board restart will not change; RAM holds read and write copies, and variable values may change as the program runs.
- BSS
Represents an uninitialized variable. Uninitialized data in RAM is initialized to 0 when the program starts.
- Other memory segments
. User_heap_stack Memory heap, malloc() applies memory to use this area; .arm. Attributes and. Debug_frame store debugging information.
Map Mapping file, ASM disassembly file
You need to specify a link script when the program compiles links. After the program is successfully compiled, a map mapping file is generated to store the memory mapping information of the program and data. The mapping file is an important auxiliary analysis file, which can obtain how functions and variables in the program are allocated to RAM and ROM. When using the image analysis function, we specify the Map mapping file outcloud_STm32f429IGTX_FireHuawei_liteos.map. The disassembly file is another important file. If a function occupies too much text or data, you can analyze the disassembly code. Using the mirror analysis feature combined with disassembly files, we can easily evaluate whether the function can be further improved. Take the main function as an example. The fragment in the mapping file is as follows. The main function is stored at 0x08000eA0 and occupies 0x38 bytes (=56 bytes).
.text.startup.main 0x08000ea0 0x38 d:/LiteOS_master/out/Cloud_STM32F429IGTx_FIRE/liblibCloud_STM32F429IGTx_FIRE.a(main.o) 0x08000ea0 main
This data is also quickly available on the LiteOS Studio image analysis page:
Below is a disassembly fragment of the main() function. As you can see, we are presenting a mixture of C code and disassembly. The first column 8000eA0 is the address, the second column is the machine code of the assembly instruction, and then the assembly code. The function starts at 0x8000eA0 and ends at 0x8000ed4. The space occupied by the function is 0x8000ED4-0x8000EA0 +0x4=0x38 bytes. If the function length is too long, combined with the analysis of disassembly code lines, positioning optimization.
08000ea0
Hello Huawei LiteOS
DATE
TIME
UINT32 ret = OsMain();
Copy the code
8000eb4: f003 fd18 bl 80048e8 d:LiteOS_mastertargetsCloud_STM32F429IGTx_FIRE/Src/main.c:55 if (ret ! = LOS_OK) { 8000eb8: b108 cbz r0, 8000ebe <main+0x1e> d:LiteOS_mastertargetsCloud_STM32F429IGTx_FIRE/Src/main.c:56 return LOS_NOK; 8000eba: 2001 movs r0, #1 d:LiteOS_mastertargetsCloud_STM32F429IGTx_FIRE/Src/main.c:62 }
OsStart(); return 0;
Copy the code
} 8000ebc: bd98 pop {r3, r4, r7, pc} 8000ebe: 4604 mov r4, r0
Hands-on test time
Let’s start coding and create different types of variables and functions to see what memory segments they allocate to and whether the actual allocation matches what we already know. Add the following code snippet above the function UINT32 app_init(VOID) in targetsCloud_STM32F429IGTX_firesrCUSER_task.c, Add pair ABC_FunName(0) in the first line of the UINT32 app_init(VOID) function. The call.
static UINT32 ABC_static_global_init = 1; UINT32 ABC_global_init = 1; UINT32 ABC_global_noInit; const UINT32 ABC_global_const = 1; static VOID ABC_Static_FunName(VOID){ printf(“ABC_static_global_init is %d.n”, ABC_static_global_init); printf(“ABC_global_init is %d.n”, ABC_global_init); printf(“ABC_global_noInit is %d.n”, ABC_global_noInit); printf(“ABC_global_const is %d.n”, ABC_global_const); }
UINT32 ABC_FunName(UINT32 ABC_num){ CHAR *ABC_var_inFun = “1234567890”; UINT32 ABC_var_inFuc_init = 1; static UINT32 ABC_static_InFuc_init = 1; static UINT32 ABC_static_InFuc_noinit; const UINT32 ABC_inFuc_const = 1; ABC_static_InFuc_noinit = 99; printf(“ABC_var_inFuc_init is %d.n”, ABC_var_inFuc_init);
printf("ABC_static_InFuc_init is %d.n", ABC_static_InFuc_init);
printf("ABC_static_InFuc_noinit is %d.n", ABC_static_InFuc_noinit);
printf("ABC_inFuc_const is %d.n", ABC_inFuc_const);
CHAR *buf = LOS_MemAlloc(m_aucSysMem0, 8);
buf[0] = ABC_var_inFun[0];
LOS_MemFree(m_aucSysMem0, buf);
(VOID)ABC_Static_FunName(); return 0;
Copy the code
}
Recompile and redisplay by clicking the refresh button on the image analysis page. All of our new symbols start with ABC_, and if we search for this keyword, we can see that the ABC_FunName function belongs to the.text code segment, and the global_init variable belongs to the.data segment, The global uninitialized variable ABC_global_noInit belongs to the. BSS segment. The static function ABC_Static_FunName, function stack, is not shown in this area. This is consistent with what we already know, as shown below, and you can try it yourself.
This article introduces the memory layout, linking scripts, mapping files in embedded development, and demonstrates how to use the image analysis features of LiteOS Studio to evaluate function space footprint in conjunction with disassembly files. LiteOS Studio is our LiteOS Internet of Things development weapon! Welcome to use this feature, and share your experience, any questions, suggestions, you can leave a message to us gitee.com/LiteOS/Lite…
This article is shared by Huawei Cloud community “Using LiteOS Studio Image analysis tool evaluation optimization LiteOS image”.
Click to follow, the first time to learn about Huawei cloud fresh technology ~