The C28x compiler divides the storage space into two parts for management, including:
1. Program storage space: contains executable code, initialized records, and tables used by switch-case.
2. Data storage space: contains external variables, static variables and system stack; generally, the storage space corresponding to each register is also classified in the data space.
For the convenience of management, different types of code and variables are often allocated to different sections. Then the division of storage space becomes a problem of allocating addresses to the sections. For example, in the following code, it is specified that the .text section will be stored in RAML1 under Page0 in RAM. The starting address of RAML1 is 0x009000 and the length is 0x001000.
MEMORY
{
/* Omit code that is not shown here */
PAGE 0 :
RAML1 : origin = 0x009000, length = 0x001000
RAML2 : origin = 0x00A000, length = 0x001000
/* Omit code that is not shown here */
}
SECTIONS
{
/* Omit code that is not shown here */
.text : > RAML1, PAGE = 0
/* Omit code that is not shown here */
}
In general, our code is not so large that it cannot be stored, but it is also possible that the code is too large to be stored, resulting in a link error such as the actual size of .text is size xxx, but the size of RAML1 is only yyy, so that the output file cannot be generated. At this time, we can increase the length of RAML1 corresponding to the above, that is, length, so that the address space allocated to the .text segment becomes larger. However, after the address space of RAML1 is expanded, it occupies the space of RAML2, resulting in address overlap. At this time, the starting position of RAML2 should be moved back and its length should be reduced accordingly to avoid address overwrite errors; after modification, it can be:
RAML1 : origin = 0x009000, length = 0x001500
RAML2 : origin = 0x00A500, length = 0x000500
Another solution is to allocate .text to other longer address spaces; if there is no existing segment with a longer address range, you can also merge existing segments. For example, delete RAML2 and merge all its addresses into RAML1, while .text is still allocated in RAML1. When deleting RAML2, please note that it can only be operated when it is not used by any segment, otherwise it will prompt that other segments cannot find the corresponding storage unit when compiling and linking.
Below we explain the meaning of each segment:
1. Initialization segment
These contain data and executable code and are usually read-only. They include:
1. cinit和.pinit
Contains a table used to initialize variables and constants. It is read-only.
C28x .cinit is limited to the 16-bit range, that is, the lower 64K range.
2 .const
This includes string constants, string literals, selection lists, and read-only variables defined with the const keyword (but excluding volatile types and assuming a small memory model).
3 .econst
Contains string constants, as well as global and static variables defined using the far keyword.
4 .switch
Stores the selection table used by the switch-case instruction.
5 .text
Usually read-only, contains all executable code, as well as constants generated by the compiler .
2. Uninitialized segments
Although uninitialized segments will not be initialized, they still need to reserve the relevant address space in the storage unit (usually RAM). They include:
1 .bss
Reserve storage space for global and static variables. When starting or loading the program, the C/C++ startup program will copy the data in the .cinit segment (usually stored in ROM) to the .bss segment.
2. ebss
Reserve storage space for global and static variables defined with the far keyword (applicable only to C code). When starting or loading the program, the C/C++ startup program will copy the data in the .cinit segment (usually stored in ROM) to the .ebss segment.
3 .stack
By default, the stack is stored in the .stack segment (refer to boot.asm), which is used to reserve storage space for the stack. The main functions of the stack are:
1) Reserve storage space for storing parameters passed to the function;
2) Allocate relevant address space for local variables;
3) Save the state of the processor;
4) Save the return address of the function;
5) Save the values of some temporary variables.
It should be noted that the .stack segment can only use the data storage unit of the lower 64K address, because the CPU's SP register is 16 bits and it cannot read the address range exceeding 64K. In addition, the compiler cannot check the stack overflow error (unless we write some code to detect it ourselves), which will lead to wrong output results, so a relatively large storage space should be allocated for the stack, and its default value is 1K words. The operation of changing the stack size can be completed through the compiler option --stack_size.
4. system
This article is citedReserve storage space for dynamic memory allocation, thereby serving dynamic memory allocation routines such as malloc, calloc, realloc, and new. If these dynamic memory management functions are not used in C/C++ code, there is no need to create a .sysmem segment.
In addition, we often mention the "stack". Here we only talk about the stack. What is the heap used for? The heap is used for dynamic memory allocation. Because RAM resources are still relatively precious on DSP , the storage space occupied by the heap cannot be expanded indefinitely. For the heap modified by the near keyword, the address space it occupies can only be up to 32K words at most; for the heap modified by the far keyword, the storage space it uses is automatically set by the compiler , and the default is only 1K words.
5 .esysmem
Allocate dynamic storage space for the far malloc function. If this function is not used, the compiler will not automatically create the .esysmem section.
For the assembler, it will automatically create three sections: .text, .bss and .data. We can use #pragma CODE_SECTION and #pragma DATA_SECTION to create more sections.
By default, the storage space allocated to each segment is configured as follows (can be changed as needed):
Finally, let's take an example of memory address allocation corresponding to an ADC register to see how the completed cmd file is completed (in fact, the memory address allocation of all registers has been done for us in TI's peripheral and header file packages, and here is a demonstration).
First, in the header file or source program that uses registers (or custom variables), specify a custom segment for the registers (or custom variables):
#ifdef __cplusplus
#pragma DATA_SECTION("AdcRegsFile")
#else
#pragma DATA_SECTION(AdcRegs,"AdcRegsFile");
#endif
volatile struct ADC_REGS AdcRegs; //Make the structure allocated in the specified segment
Then, in the cmd file, allocate the AdcRegsFile segment to the ADC memory area under SECTIONS , and define the starting position and length of the ADC memory area in MEMORY .
MEMORY
{
PAGE 0: /* Program Memory */
/* Omit the display of irrelevant content */
PAGE 1: /* Data Memory */
/* Omit the display of irrelevant content */
ADC : origin = 0x007100, length = 0x000020 /* ADC registers */
/* Omit the display of irrelevant content */
}
SECTIONS
{
/* Omit the display of irrelevant content */
AdcRegsFile : > ADC, PAGE = 1
/* Omit the display of irrelevant content */
}
The above is a complete example of customizing segments and specifying memory areas. If you do not need such customization, you can ignore it and use existing ones, such as the cmd file that can be used in an example.
Previous article:Design of serial communication system based on DSP and touch screen
Next article:DSP Programming Skills 17---Very "Critical" Keywords
- Popular Resources
- Popular amplifiers
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- What is the difference between low inertia and high inertia of servo motors?
- Which file in the library is the MicroPython UART source code for ESP32?
- Battery power collection
- TI DSP specific model meaning
- What is a connector?
- Please help me analyze how this circuit works
- Help
- How to set up PCB routing like this?
- Dear bachelors, do you cook your dinner yourself or eat out?
- [Popular Science] Usage Scenarios and Precautions for Common Probes & Differential Probes
- Former ZTE Labor Union Chairman Sentenced to 20 Years for Illegal Fund Raising of 2.119 Billion Yuan