Program Size: Code=8040 RO-data=133356 RW-data=36 ZI-data=1876
时间: 2025-07-29 11:18:49 浏览: 20
<think>我们正在讨论Keil MDK编译后Program Size中Code、RO-data、RW-data、ZI-data的含义以及它们对内存占用的影响。用户可能遇到了内存不足的问题,需要理解这些数据来优化程序。
在Keil MDK的编译输出中,Program Size通常显示如下格式:
```
Program Size: Code=xxxx RO-data=xxxx RW-data=xxxx ZI-data=xxxx
```
这些字段分别代表:
1. **Code(代码段)**:存放程序的可执行代码(机器指令),位于Flash(ROM)中。例如函数、中断服务程序等编译后的指令。
2. **RO-data(只读数据段)**:存放程序中定义的常量(如`const`修饰的变量)和字符串常量。这部分数据也存储在Flash(ROM)中,因为它们在运行时不可修改。
3. **RW-data(可读写数据段)**:存放已初始化的全局变量和静态变量。这些变量在程序启动时会被初始化(从Flash复制到RAM中),因此它们占用两种存储空间:
- Flash空间:存储初始值(在烧录时写入Flash)
- RAM空间:程序运行时存放变量(在启动时从Flash复制初始值到RAM)
4. **ZI-data(零初始化数据段)**:存放未初始化或显式初始化为0的全局变量和静态变量。这些变量在程序启动时由启动代码初始化为0,因此:
- 不占用Flash空间(因为初始值都是0,无需存储)
- 只占用RAM空间(在运行时分配并初始化为0)
### 内存占用计算公式
- **Flash总占用** = `Code` + `RO-data` + `RW-data`(因为RW-data的初始值需要存储在Flash中)
- **RAM总占用** = `RW-data` + `ZI-data`(运行时数据全部在RAM中)
例如,如果编译输出为:
```
Program Size: Code=3920 RO-data=320 RW-data=40 ZI-data=1024
```
则:
- Flash占用 = 3920 + 320 + 40 = 4280 字节
- RAM占用 = 40 + 1024 = 1064 字节
### 内存分布图示
```plaintext
+---------------------+
| Flash (ROM) |
+---------------------+
| Code (程序代码) | 3920字节
+---------------------+
| RO-data (只读数据) | 320字节
+---------------------+
| RW-data (初始值) | 40字节 → 复制到RAM
+---------------------+
+---------------------+
| RAM (运行时) |
+---------------------+
| RW-data (已初始化) | 40字节 (从Flash复制初始值)
+---------------------+
| ZI-data (0初始化) | 1024字节 (启动时初始化为0)
+---------------------+
| 堆(Heap)和栈(Stack) | 通常不在Program Size中显示,需单独设置
+---------------------+
```
### 优化建议
1. **减少Flash占用**:
- 优化代码(如使用编译器优化选项`-O2`、`-Os`)
- 减少常量数据(如大型查找表、字符串)
- 压缩数据(如将`int`数组改为`uint8_t`数组)
2. **减少RAM占用**:
- 减少全局变量(改用局部变量)
- 避免大数组定义为全局变量(特别是ZI-data)
- 动态内存分配谨慎使用(防止堆碎片)
### 查看详细内存分布
在Keil中,编译后生成的`.map`文件包含详细的内存分配情况。通过以下步骤查看:
1. 编译项目后,在`Build Output`窗口底部找到`.map`文件路径
2. 打开该文件,搜索`Memory Map of the image`查看各段地址和大小
> 提示:STM32F103C8T6的Flash为64KB(0x10000),RAM为20KB(0x5000)。若`Code+RO-data+RW-data`超过64KB,则会出现链接错误(如L6406E)[^1]。
§§相关问题§§
1. 如何解读Keil生成的.map文件?
2. 如何优化STM32程序的RAM使用?
3. Keil中分散加载文件(Scatter File)的高级配置技巧?</think>### Keil MDK 内存占用详解(Program Size)
在 Keil MDK 编译后显示的 **Program Size** 包含四个关键参数,它们反映了程序在 STM32 微控制器中的内存分布情况:
```
Program Size:
Code=3920 RO-data=320 RW-data=40 ZI-data=1024
```
#### 1. **Code (代码段)**
- **含义**:编译后的机器指令(可执行代码)
- **存储位置**:Flash 存储器(非易失性)
- **包含内容**:
- 函数代码
- 中断服务程序
- 跳转表
- **优化建议**:
- 使用编译器优化选项(`-O2`/`-O3`)
- 移除未使用的函数(`--gc-sections`)
- **计算公式**:
$$\text{Flash占用} \geq \text{Code}$$
#### 2. **RO-data (只读数据)**
- **含义**:Read-Only 常量数据
- **存储位置**:Flash 存储器
- **包含内容**:
- `const` 修饰的全局变量
- 字符串常量(如 `"Hello"`)
- 初始化的全局静态变量
- **示例**:
```c
const uint32_t MAX_VALUE = 1000; // 计入 RO-data
char *msg = "Error!"; // 字符串常量计入 RO-data
```
- **计算公式**:
$$\text{Flash占用} = \text{Code} + \text{RO-data} + \text{RW-data}$$
#### 3. **RW-data (可读写数据)**
- **含义**:Read-Write 初始化变量
- **存储位置**:
- **Flash**:存储初始值
- **RAM**:运行时值(启动时从 Flash 复制)
- **包含内容**:
- 初始化的全局变量
- 初始化的静态变量
- **示例**:
```c
int counter = 0; // 计入 RW-data
static float calib = 1.2; // 计入 RW-data
```
- **内存关系**:
$$\text{RAM占用} \geq \text{RW-data} + \text{ZI-data}$$
#### 4. **ZI-data (零初始化数据)**
- **含义**:Zero-Initialized 未初始化变量
- **存储位置**:RAM
- **包含内容**:
- 未初始化的全局变量
- 未初始化的静态变量
- 初始化为 0 的变量
- **关键特性**:
- **不占用 Flash**(启动时由启动代码初始化为 0)
- **示例**:
```c
uint8_t buffer[1024]; // 计入 ZI-data
static char log_buf[256]; // 计入 ZI-data
```
### 内存分布图示
```plaintext
+---------------------+ +---------------------+
| FLASH | | RAM |
+---------------------+ +---------------------+
| Code (3920 bytes) | | |
|---------------------| | RW-data (40 bytes) | ← 从Flash复制初始值
| RO-data (320 bytes) | |---------------------|
|---------------------| | ZI-data (1024 bytes)| ← 启动时清零
| RW-data初始值(40字节)| |---------------------|
+---------------------+ | Heap/Stack | (未在Program Size中显示)
```
### 关键公式总结
1. **Flash 总占用**:
$$Flash_{\text{total}} = \text{Code} + \text{RO-data} + \text{RW-data}$$
2. **RAM 总占用**:
$$RAM_{\text{total}} = \text{RW-data} + \text{ZI-data} + \text{Stack} + \text{Heap}$$
3. **启动后最小 RAM 需求**:
$$RAM_{\text{min}} = \text{RW-data} + \text{ZI-data}$$
> ⚠️ 注意:实际 RAM 占用还包括堆栈空间(需在启动文件中配置),Program Size 不显示此部分[^1]。
### 优化策略
1. **减少 Flash 占用**:
- 压缩常量数据(如使用 `uint8_t` 代替 `int`)
- 启用 LTO(Link Time Optimization)
2. **减少 RAM 占用**:
- 将大数组改为 `const`(移入 RO-data)
- 动态分配大内存(替代全局数组)
3. **监控工具**:
- 查看 `.map` 文件获取详细段分布
- 使用 `fromelf --text -c xxx.axf > disasm.txt` 反汇编分析
阅读全文
相关推荐




















