The RO, RW, and Zi data described in the arm system have a similar and non-existent understanding. During this time, we have carefully understood it and found some rules, I have understood some things that I did not understand in my previous books. I think many people may also be confused with me, we hope to help you understand RW and Zi.
To learn about ro, RW, and Zi, you must first understand the following knowledge:
Arm program composition:
The "arm program" mentioned here refers to the program being executed in the arm system, rather than the bin image file stored in the Rom.
An arm program contains three parts: RO, RW, and Zi.
Ro is the instruction and constant in the program.
RW is the initialized variable in the program.
Zi is an uninitialized variable in the program.
The above three points can be understood:
Ro is readonly,
RW is read/write,
Zi is zero.
Arm image file composition:
The so-called arm image file refers to the binary file burned into the ROM and also becomes an image file. The following is called an image file.
The image file contains Ro and RW data. The reason why the image file does not contain the Zi data is that the Zi data is 0 and does not need to be included. You only need to clear the region where the Zi data is located before running the program. It wastes storage space.
Q: Why must image contain Ro and RW?
A: The commands and constants in RO and the initialized variables in RW cannot be "born out of nothing" like Zi.
Arm Program Execution Process:
From the above two points, we can know that the image file burned to the Rom is not exactly the same as the actual running arm program. Therefore, it is necessary to understand how the arm Program
The image in the ROM reaches the actual running status.
In fact, commands in Ro should have at least the following functions:
1. Move RW from Rom to ram. Because RW is a variable, the variable cannot exist in Rom.
2. Clear all the ram regions where Zi is located. Because the Zi region is not in the image, the program needs to clear the desired Ram region based on the Zi address and size given by the compiler. Zi is also a variable. Similarly, the variable cannot exist in Rom.
At the initial stage of the program running, the C program can access the variables normally after the commands in RO Have completed these two tasks. Otherwise, only codes without variables can be run.
After talking about what Ro, RW, and Zi are, I will give a few examples to illustrate Ro, RW, what does Zi mean in C.
1: RO
Looking at the following two programs, there is a separate statement between them. This statement declares a character constant. Therefore, as we mentioned earlier, they should be only one byte different from RO data (the character constant is 1 byte ).
Prog1:
# Include
Void main (void)
{
;
}
Prog2:
# Include
Const char a = 5;
Void main (void)
{
;
}
After prog1 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 60 0 96 0 grand totals
========================================================== ==========================================================
Total Ro size (codes + RO data) 1008 (0.98kb)
Total RW size (RW data + Zi data) 96 (0.09kb)
Total Rom size (code + RO Data + RW data) 1008 (0.98kb)
========================================================== ==========================================================
After prog2 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 61 0 96 0 grand totals
========================================================== ==========================================================
Total Ro size (code + RO data) 1009 (0.99kb)
Total RW size (RW data + Zi data) 96 (0.09kb)
Total Rom size (code + RO Data + RW data) 1009 (0.99kb)
========================================================== ==========================================================
The information after the above two programs are compiled can be seen:
The RO of prog1 and prog2 contains two types of data: code and Ro data. Their only difference is that prog2's Ro data is 1 byte more than prog1. This is consistent with previous speculation.
If an instruction is added instead of a constant, the result should be the code data size difference.
2: RW
Let's look at the two programs again. There is only one difference between them: "initialized variables". According to the previous instructions, initialized variables should be included in RW, therefore, the size of RW is different between two programs.
Prog3:
# Include
Void main (void)
{
;
}
Prog4:
# Include
Char A = 5;
Void main (void)
{
;
}
After prog3 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 60 0 96 0 grand totals
========================================================== ==========================================================
Total Ro size (codes + RO data) 1008 (0.98kb)
Total RW size (RW data + Zi data) 96 (0.09kb)
Total Rom size (code + RO Data + RW data) 1008 (0.98kb)
========================================================== ==========================================================
After prog4 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 60 1 96 0 grand totals
========================================================== ==========================================================
Total Ro size (codes + RO data) 1008 (0.98kb)
Total RW size (RW data + Zi data) 97 (0.09kb)
Total Rom size (code + RO Data + RW data) 1009 (0.99kb)
========================================================== ==========================================================
It can be seen that the difference between prog3 and prog4 is indeed only one byte between RW data. This byte is caused by an initialized variable ".
3: Zi
Let's look at the two programs. The difference between them is an uninitialized variable "A". From the previous understanding, we can infer that there should be only a difference in the size of Zi between the two programs.
Prog3:
# Include
Void main (void)
{
;
}
Prog4:
# Include
Char;
Void main (void)
{
;
}
After prog3 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 60 0 96 0 grand totals
========================================================== ==========================================================
Total Ro size (codes + RO data) 1008 (0.98kb)
Total RW size (RW data + Zi data) 96 (0.09kb)
Total Rom size (code + RO Data + RW data) 1008 (0.98kb)
========================================================== ==========================================================
After prog4 is compiled, the information is as follows:
========================================================== ==========================================================
Code Ro data RW data Zi data debug
948 60 0 97 0 grand totals
========================================================== ==========================================================
Total Ro size (codes + RO data) 1008 (0.98kb)
Total RW size (RW data + Zi data) 97 (0.09kb)
Total Rom size (code + RO Data + RW data) 1008 (0.98kb)
========================================================== ==========================================================
The compiled results fully conform to the assumption that only the size of the Zi data is 1 byte different. This byte is caused by an uninitialized trans variable ".
Note: If a variable is initialized to 0, the variable will be processed in the Zi region in the same way as the volume of changes not initialized.
That is, in the arm C program, all uninitialized variables are automatically initialized to 0.
Summary:
1: The commands and constants in C are compiled into Ro data.
2: The variable in C that is not initialized or initialized to 0 is compiled with Zi data.
3: Data of RW Type is compiled for a variable initialized to a non-0 value in C.
Appendix:
Program compilation command (assuming the name of the C program is TST. C ):
ARMCC-c-o TST. o tst. c
Armlink-noremove-elf-nodebug-Info totals-Info sizes-Map-list AA. Map-o tst. Elf TST. o
The compiled information is in the AA. Map File.
Rom mainly refers to: NAND Flash, nor flash
Ram mainly refers to psram, SDRAM, SRAM, and ddram.
Image $ ?? $ Limit description
For those who have just learned arm, if they analyze its startup code, they often do not understand the meanings of the following variables: | image $ Ro $ limit |, | image $ RW $ base |,
| Image $ Zi $ base |.
First, declare that the debugging software I used is ads1.2. After compiling the program, compile and link it. Select make in ads1.2 and
The errors and warnings dialog box displays the compilation and link results in this column. If there are no errors, you can see the image component at the end of the file.
Sizes, followed by the number of bytes of code, RO data, RW data, Zi data, and debug projects. Finally, there is a statistical data:
Code 163632, RO data 20939, RW data 53, Zi data 17028
Tatal Ro size (code + RO data) 184571 (180.25kb)
Tatal RW size (RW data + Zi data) 17081 (16.68 KB)
Tatal Rom size (code + RO Data + RW data) 184624 (180.30 KB)
The subsequent bytes are calculated based on different user programs. The following example describes the calculation of these variables.
In the debug settings of ads, There Is A Linker/ARM linker column, and there is a Ro base option in the output option. There should be an address below. Here I am
0x0c100000. The RW base address is 0x0c200000, and the options option contains the image entry point, which is the entry address of an initial program.
Here is 0x0c100000.
With the above information, we can fully understand how these variables come from:
| Image $ Ro $ base | = image entry point = 0x0c100000; indicates the starting address for storing program code
| Image $ Ro $ limit | = starting address of the program code + code length + 1 = 0x0c100000 + tatal Ro size + 1
= 0x0c100000 + 184571 + 1 = 0x0c100000 + 0x2d0fb + 1
= 0x0c12d0fc
| Image $ RW $ base | = 0x0c200000; specified by RW base address
| Image $ RW $ limit | = | image $ RW $ base | + RW data 53 = 0x0c200000 + 0x37 (multiples of 4, 0 to 55, 56 units in total)
= 0x0c200037
| Image $ Zi $ base | = | image $ RW $ limit | + 1 = 0x0c200038
| Image $ Zi $ limit | = | image $ Zi $ base | + Zi data 17028
= 0x0c200038 + 0x4284
= 0x0c2042bc
It can also be calculated as follows:
| Image $ Zi $ limit | = | image $ RW $ base | + tatalrwsize (rwdata + zidata) 17081
= 0x0c200000 + 0x42b9 + 3 (to be a multiple of 4)
= 0x0c2042bc
Note: scatter file (Distributed description file) is used for armlink input parameters. It specifies the download and runtime location of each region inside the image file. Armlink will
Generate regional-related Symbols Based on the scatter file, which are global for users to create runtime environments. (Note: When scatter file is used
Image $ RW $ base, image $ RW $ limit, image $ Ro $ base, image $ Ro $ limit, image $ Zi $ base, and
Image $ Zi $ limit)
Generally, a program includes read-only segments and data segments that can be read and written. In the integrated development environment of arm, read-only code segments and constants are called Ro segments (readonly). read-write global variables and static variables are called RW segments (readwrite ); the variable to be initialized to zero in the RW segment is called the Zi segment (zeroinit ). For embedded systems, program images are stored in some non-volatile devices such as flash memory. during runtime, the RW segment of the program must be reloaded into the read/write Ram. This involves loading and running time domains of programs. Simply put, the loading time domain of a program refers to the state in which the program is burned into flash, and the running time domain refers to the state in which the program is executed. In simple cases, you can specify Ro base and RW base in the arm linker option of the analyticdb integrated development environment to inform the connector of the connection Base Address of RO and RW. In complex cases, for example, when the RO segment is divided into several parts and mapped to multiple locations in the bucket, you need to create a text file called "distributed load description file, notifies the connector to connect a part of the program to an address space in the memory. It should be noted that the definition in the Distributed Loading description file should be based on the memory distribution after system redirection. After the boot program completes the initialization task, the main program should be transferred to ram for running to speed up the system.
What is an arm image file? The arm image file is actually an executable file, including the bin or hex format, which can be directly burned into the ROM for execution. During the axd debugging process, we debug the axf file, which is actually an image file. It only adds a file header and some debugging information to the binfile. Generally, an image file consists of three output segments (RO, RW, and Zi. The so-called domain refers to the region where the entire bin image file is located. It is divided into loading and running domains. The loading domain is the work area where the image file is statically stored. Generally, the address space of the entire binfile in Flash is the loading domain. Of course, the program will not be executed in flash, generally, jobs are moved to the SDRAM to run. The address space in which the jobs are moved to the SDRAM is the runtime domain. The entered Code generally includes the code part and data part. This is the so-called input segment. After compilation, it becomes the RO and RW segments in the binfile, and the so-called Zi segments, this is the output segment. For the output segment in the loading field, generally the RO segment is followed by the RW segment, and the RW segment is followed by the Zi segment. These output segments are not consecutive in the running domain, but RW and Zi must be connected. Data in the Zi and RW segments can be RW attributes.
| Image $ Ro $ base | image $ Ro $ limit | image $ RW $ base | image $ Zi $ base | image $ zi $ limit | these variables are notified by the compiler, we can see their values in the MAKEFILE file. They indicate the address space of each output segment in the runtime domain | image $ Ro $ base | is the starting address of the RO segment in the runtime domain, | image $ Ro $ limit | it is the end address of the RO segment in the running domain. And so on. We can specify it in linker output. In simple mode, RO base corresponds to | image $ Ro $ base |, RW base corresponds to | image $ RW $ base | because RW is connected to Zi, | image $ Zi $ base | equal to | image $ Zi $ limit |. other values are automatically calculated by the compiler.
Below is the handling part of the 2410 startup code. I will give a comment:
Baseofrom DCD | image $ Ro $ base |
Topofrom DCD | image $ Ro $ limit |
Baseofbss DCD | image $ RW $ base |
Baseofzero DCD | image $ Zi $ base |
Endofbss DCD | image $ Zi $ limit |
ADR r0, resetentry; resetentry is the starting address of the reset operation time domain, which is generally 0 in Boot Nand
LDR R2, baseofrom;
CMP r0, r2
Ldreq r0, topofrom; topofrom = 0x30001de0, end of the code segment address
Beq initram
LDR R3, topofrom
; Part 1: Move Ro to SDRAM through comparison. the destination address is from | image $ Ro $ base | to | image $ Ro $ limit | End
0
Ldmia R0 !, {R4-r7}
Stmia R2 !, {R4-r7}
CMP R2, R3
BCC % B0;
; Part 2: Move the RW segment to SDRAM. the destination address is from | image $ RW $ base | start to | image $ Zi $ base | End
Sub R2, R2, R3; r2 = 0
Sub r0, R0, r2
Initram; carry RW to baseofbss
LDR R2, baseofbss; topofrom = 0x30001de0, baseofrw
LDR R3, baseofzero; baseofzero = 0x30001de0
0
CMP R2, R3
Ldrcc R1, [R0], #4
Strcc R1, [R2], #4
BCC % B0
; Part 3: Initialize the SDRAM Zi to 0 and the address ranges from | image $ Zi $ base | to | image $ Zi $ limit |
MoV r0, #0; init 0
LDR R3, endofbss; endofbss = 30001e40
1
CMP R2, R3
Strcc r0, [R2], #4
BCC % B1