keil编译后code,RO-data,RW-data,ZI-data含义及mcu的flash实际存储数据

本文介绍了Keil编译器中不同内存段的作用,包括Code、RO-data、RW-data和ZI-data,并解释了它们如何占用ROM和RAM空间。此外还详细说明了程序启动时ROM中的指令如何处理RW和ZI数据。

keil编译后会有一行:Program Size:Code=xxx RO-data=xxx RW-data=xxx ZI-data=xxx

Code 代表执行的代码,程序中所有的函数都位于此处。

RO-data 代表只读数据,程序中所定义的全局常量数据和字符串都位于此处。

RW-data 代表已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量位于此处。

ZI-data 代表未初始化的读写数据,程序中定义了但没有初始化的全局变量和静态变量位于此处。ZI英语是zero initial,就是程序中用到的变量并且被系统初始化为0的变量的字节数,keil编译器默认是把你没有初始化的变量都赋值一个0,这些变量在程序运行时是保存在RAM中的。

2.如果你查看.map文件,如下例子:

==============================================================================

    Total RO  Size (Code + RO Data)                 2980 (   2.91kB)
    Total RW  Size (RW Data + ZI Data)               104 (   0.10kB)
    Total ROM Size (Code + RO Data + RW Data)       2988 (   2.92kB)

==============================================================================

Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的ROM的字节总数,也就是说程序所下载到ROM flash 中的大小。为什么Rom中还要存RW,因为掉电后RAM中所有数据都丢失了,每次上电RAM中的数据是被重新赋值的,每次这些固定的值就是存储在Rom中的,为什么不包含ZI段呢,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可,包含进去反而浪费存储空间。

实际上,ROM中的指令至少应该有这样的功能:
       1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
       2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中。
       在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。

你提供的编译输出信息如下: ``` Program Size: Code=403628 RO-data=424500 RW-data=8980 ZI-data=280980 ``` 我们来一步步解释 **如何计算 ROM 和 RAM 占用**,并根据你的芯片 `STM32H723ZGT6` 计算剩余空间。 --- ## ✅ 一、理解 ARM 编译器的程序大小含义(来自 `.map` 或编译日志) | 段 | 含义 | 对应存储区域 | |------------|------|---------------| | **Code** | 程序代码(机器指令) | FlashROM) | | **RO-data** | Read-Only 数据(如 const 全局变量、字符串常量、字体数组等) | FlashROM) | | **RW-data** | Read/Write 数据(已初始化的全局/静态变量) | RAM(运行时从 Flash 复制过来) | | **ZI-data** | Zero-initialized Data(未初始化或初值为0的全局变量) | RAM(启动时清零) | > 📌 总结: - **FlashROM)占用 = Code + RO-data** - **RAM(运行时)占用 = RW-data + ZI-data** --- ## ✅ 二、计算当前使用的 ROM 和 RAM ### 🔢 计算公式: ```text Total ROM (Flash) = Code + RO-data = 403,628 + 424,500 = 828,128 字节 ≈ **808.7 KB** Total RAM (Runtime) = RW-data + ZI-data = 8,980 + 280,980 = 289,960 字节 ≈ **283.2 KB** ``` --- ## ✅ 三、查看 STM32H723ZGT6 的资源规格 查阅 [ST 官方数据手册](https://www.st.com/resource/en/datasheet/stm32h723zg.pdf) | 参数 | 值 | |------|-----| | **型号** | STM32H723ZGT6 | | **Flash** | **512 KB**(注意!不是 1MB)❗️ | | **SRAM** | 总共 128 KB(包括 DTCM、ITCM、AXI SRAM 等) | Wait! ❗️这里出现矛盾了! 👉 你算出来用了 **808.7 KB Flash**,但 H723ZGT6 只有 **512 KB Flash**! 这说明:**你的程序已经严重超出了 Flash 容量!** --- ## ⚠️ 四、关键问题:STM32H723 vs H725 —— Flash 区别很大! 你可能混淆了两个型号: | 型号 | Flash | RAM | 封装 | 备注 | |------|--------|------|-------|------| | **STM32H723ZGT6** | **512 KB** | 128 KB | LQFP144 | 主流款 | | **STM32H725ZET6** | **512 KB + 64 KB Bank2** | 更多缓存 | - | 外部 QSPI 支持更好 | | **STM32H723VGT6 / ZGTx** | 都是 512 KB | 同上 | - | 没有更大 Flash 版本 | ✅ 所以结论是: > ❌ **你当前程序(808KB Flash)无法烧录到 STM32H723ZGT6 上!会报 "truncated" 或写入失败。** --- ## ✅ 五、解决方案与优化建议 ### ✅ 方案 1:换更大 FlashMCU(推荐) 如果你必须保留所有功能,考虑升级到: - **STM32H743ZGT6 / NGT6** → **1 MB Flash**, 128 KB + 64 KB + 32 KB 多级 RAM - 或使用 WLCSP 封装的 H7B3/H7A3 系列(更高密度) --- ### ✅ 方案 2:大幅裁剪程序体积(适用于仍在开发阶段) #### 🔽 减少 Flash 使用(目标:≤ 480 KB) | 优化项 | 方法 | 可节省 | |--------|------|--------| | **字体资源** | 中文字体太大!裁剪只保留需要的字符 | ✅ 最高可省 300~400 KB | | **图片格式** | 不要用 RAW/BMP,改用压缩的 PNG/LZ4/SPIFFS 存储 | ✅ 节省几十到上百 KB | | **LVGL 配置** | 修改 `lv_conf.h` 关闭不用模块 | ```c #define LV_USE_ANIMATION 1 // 必要才开 #define LV_USE_RLE 0 // 不用 RLE 压缩图像 #define LV_COLOR_DEPTH 16 // 不用 32 位色深 #define LV_FONT_SUBPX_BGR 0 // 关闭子像素渲染 #define LV_BUILD_EXAMPLES 0 // 关闭示例 ``` | | | ~20–50 KB | | **函数优化** | 使用 `-Os` 编译选项(代码尺寸优先) | ✅ 必须开启 | | **调试信息** | 移除 printf、log 输出、断言等 | ✅ 可节省数 KB | 🔧 示例:一个完整中文 UI 字体(GBK 全集)可达 **400~700 KB**,而仅包含常用 200 字的字体仅需 **20~40 KB**! 👉 推荐工具:[LVGL Font Converter](https://lvgl.io/tools/font) → 输入“欢迎设置系统退出确认取消”等实际用字。 --- ### ✅ 方案 3:将部分资源放在外部存储(QSPI Flash / SD card) 如果硬件支持: - 使用 **QSPI NOR Flash**(如 W25Q128JV,16MB)存放: - 字体文件(动态加载) - 图片资源 - 文件系统(FATFS + SPIFFS) 然后在运行时读取并解压使用。 LVGL 支持: - `lv_fs_if_fatfs.c` → 从 SD 卡加载图片 - 自定义字体加载器 → 从外部 Flash 读取字模 这样主 Flash 只留核心逻辑。 --- ## ✅ 六、检查实际可用 RAM 是否足够? 你当前 RAM 使用: ```text RAM used = RW-data + ZI-data = 8,980 + 280,980 = 289,960 B ≈ 283.2 KB ``` 但 H723ZGT6 只有 **128 KB RAM**! ➡️ 这也 **超了 2.2 倍以上!** 这意味着:**即使你能烧录进去,程序也无法运行(启动即崩溃)** ### 💡 RAM 超限常见原因: - 动态分配大缓冲区(如 `lv_color_t buf[480*272]` ×2 → 1MB) - 开启双帧缓冲(double buffering)+ DMA2D cache - GUI 直接渲染到大内存块(未使用 partial refresh) 🔧 解决办法: - 使用 **Partial Rendering(部分刷新)** - 使用 **1/4 帧缓冲 + flush 回调逐行绘制** - 使用 `DMA2D` + `LTDC` 减少 CPU 参与 - 设置 `LV_MEM_SIZE` 到合理值(如 64KB 而非默认 96KB) --- ## ✅ 七、最终总结表 | 项目 | 当前用量 | STM32H723ZGT6 容量 | 是否超出? | 建议 | |------|----------|---------------------|-------------|-------| | **Flash (ROM)** | **808.7 KB** | **512 KB** | ❌ 超出 296.7 KB | 裁剪字体或换大 Flash 芯片 | | **RAM (运行时)** | **283.2 KB** | **128 KB** | ❌ 超出 155.2 KB | 减少帧缓存、优化内存池 | --- ## ✅ 如何查看剩余空间?(Keil MDK 示例) 在 Keil 编译完成后,底部会显示: ``` Program Size: Code=xxx RO-data=xxx RW-data=xxx ZI-data=xxx FromELF: creating hex file... ``` 你可以手动计算: ```bash Flash_usage = Code + RO-data # 烧录到 Flash 的总量 RAM_usage = RW-data + ZI-data # 运行时占用 RAM ``` 再对比芯片规格即可判断是否可行。 或者使用命令行脚本自动化检测。 --- ###
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

spdian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值