When developing MCU code, we often have some doubts about how variables enter the RAM area of MCU after compilation, especially when developing with keil. Later, after contacting gcc compiler and self-developed MCU, I finally understood this problem. In fact, the compiled variables are placed behind the code in the bin file (data is stored in bin, and BSS stores length information in Bin). When the program runs, it will actively load the data of this area into the RAM area in turn.
After the code is written and compiled, the variables in the data area of the code will be placed behind the code, and the variables in the BSS area will only be stored in bin. Of course, this rule is also determined by the link file. An example is shown below
After the program runs, there will be an assembly code in the code before it officially enters the C environment. The main function is to copy the data area memory into RAM in turn. After the copy is completed. Set the memory of the following area with the same length as the description of the BSS area to 0.
This also shows why the value of the BSS area is set to 0 because there is no type in memory. If you do not set all 0, no other value can confirm the value of the actual type. (for example, if it is set to 1, different types will correspond to different values. Int is 0x1111 and short is 0X11)
But we don’t see such code in keil. Keil’s assembly code is as follows:
Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
After this code is executed, it will jump to__ It is executed in the main function. The main thing to note is that it does not directly jump to the main function we have written. In__ Main has many operations, including loading variables into RAM area. After execution, we will jump to the main function developed by ourselves for execution.
The following code is the code for loading variables under the gcc compiler. There are several variables. The starting address of data in bin file, the starting and ending addresses of data in RAM area, and the starting and ending addresses of BSS in RAM area are obtained from LD file.
After running the following code, all variables in the program are loaded into the RAM area.
/* * The ranges of copy from/to are specified by following symbols * __etext: LMA of start of the section to copy from. Usually end of text * __data_start__: VMA of start of the section to copy to * __data_end__: VMA of end of the section to copy to * * All addresses must be aligned to 4 bytes boundary. */ lrw r1, __ Erodata // the starting address of data in the bin file lrw r2, __ data_ start__ // Starting address of data in RAM lrw r3, __ data_ end__ // End address of data in RAM Subu R3, R2 // R3 is the length of data Cmpnei R3, 0 // judge whether the length is 0 bf .L_loop0_done .L_ Loop0: // move the data in the bin file to ram in turn ldw r0, (r1, 0) stw r0, (r2, 0) addi r1, 4 addi r2, 4 subi r3, 4 cmpnei r3, 0 bt .L_loop0 .L_loop0_done: /* * The BSS section is specified by following symbols * __bss_start__: start of the BSS section. * __bss_end__: end of the BSS section. * * Both addresses must be aligned to 4 bytes boundary. */ lrw r1, __bss_start__ lrw r2, __bss_end__ movi r0, 0 subu r2, r1 cmpnei r2, 0 bf .L_loop1_done .L_ Loop1: // copy the data in BSS to 0 stw r0, (r1, 0) addi r1, 4 subi r2, 4 cmpnei r2, 0 bt .L_loop1 .L_loop1_done: