开发日志:一个属性前缀,为stm32程序节省 500KB Flash 空间

问题浮现:惊现RW-data独自占用545KB

最近在做一个有关LVGL的嵌入式STM32项目,完成功能编译后,顺便看了一下编译输出信息,却看到了一个令人意外的结果:

复制代码
Program Size:
  Code=440404 RO-data=168592 RW-data=557368 ZI-data=48696

简单相加:440404 + 168592 + 557368 = 1166364,这意味着程序对 Flash 的占用竟然达到了 1.1MB 以上。

更值得关注的是,RW-data 独自占用了 557368 字节(约 545KB)。

定位元凶:LVGL 的显存缓冲区

通过查看链接生成的 .map 文件,我迅速将问题定位到了 lv_port_disp.c 文件。该文件为 LVGL 显示驱动分配了两个巨大的缓冲区:

c 复制代码
static uint8_t buf_2_1[MY_DISP_HOR_RES * MY_DISP_VER_RES / 5 * BYTE_PER_PIXEL];
static uint8_t buf_2_2[MY_DISP_HOR_RES * MY_DISP_VER_RES / 5 * BYTE_PER_PIXEL];

这两个缓冲区用于 UI 的渲染和缓存,总大小约为 490KB。关键在于,它们作为未初始化的全局变量,在运行时确实需要占用同等大小的 RAM,但其初始内容全为0,完全不应该在 Flash 中保存一份副本。

理论上,这类变量应被归类为 ZI(Zero-Initialized)数据,只在链接脚本中预留 RAM 空间,上电后由启动代码统一清零即可,不占用宝贵的 Flash。

深入分析:这段数据为什么被隔归类为RW-data?

查询资料,咨询AI,发现了 AC6 的一个重要编译约定:

AI Gemini给出的回答:

在 AC6 中,凡是使用 attribute((section("name"))) 自定义段的变量,编译器默认会将其视为 PROGBITS 类型(即需要初始内容的 RW Data)。即使内容全为0,链接器也会在 Flash 中为其分配空间,用于存储"初始的0值",并在启动时将其复制到 RAM。

这正是我们的 490KB 缓冲区占用 Flash 的根本原因。

解决方案:添加 .bss. 前缀

根据Gemini给出的方法,我成功将这490KB的数据转换为了ZI数据。

c 复制代码
LV_ATTRIBUTE_MEM_ALIGN
__attribute__((section(".bss.display_buf1"))) // 注意前缀
static uint8_t buf_2_1[MY_DISP_HOR_RES * MY_DISP_VER_RES / 5 * BYTE_PER_PIXEL];

LV_ATTRIBUTE_MEM_ALIGN
__attribute__((section(".bss.display_buf2"))) // 注意前缀
static uint8_t buf_2_2[MY_DISP_HOR_RES * MY_DISP_VER_RES / 5 * BYTE_PER_PIXEL];

并且在sct文件中也要同步修改:

sct 复制代码
LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_RAM2 0x30020000 0x00020000  {
   .ANY (+RW +ZI)
  }
  RW_RAM3 0x30040000 0x00008000  {
   .ANY (+RW +ZI)
  }
  RW_IRAM1 0x20000000 0x00020000  { 
    *(STACK, +ZI) 
    .ANY (+RW +ZI)
  }
  RW_IRAM2 0x24000000 0x00080000{ 
    *(.bss.display_buf1) ;这里也要添加.bss.
    *(.bss.display_buf2);这里也要添加.bss.
  }
}

优化成果:Flash 占用骤降 42%

应用上述修改后,重新编译项目,结果对比显著:

优化前:

复制代码
Program Size:
  Code=440404 RO-data=168592 RW-data=557368 ZI-data=48696
Flash 占用 ≈ 1166364 字节 (1.11 MB)

优化后:

复制代码
text
Program Size:
  Code=440372 RO-data=168592 RW-data=65848 ZI-data=540208
Flash 占用 ≈ 674812 字节 (659 KB)
相关推荐
威嵌神州5 分钟前
复旦微 FMQL100TAI 开发 8 问:仿真器、系统、接口高频问题解答
人工智能·嵌入式硬件·fpga开发
H_oRIZoN_18 分钟前
Linux入门DAY45 IMX6ULL 裸机开发笔记:汇编点灯、C 语言点灯、GIC 中断梳理
linux·单片机·嵌入式硬件
怀民民民21 分钟前
嵌入式软件学习路线与项目实践记录:STM32、FreeRTOS、Linux 与 OpenMV
stm32·freertos·嵌入式软件·嵌入式linux·openmv
离凌寒1 小时前
一、关于linux开发板上移植ubuntu根文件系统并配置桌面环境笔记记录
驱动开发·单片机
Rsingstarzengjx2 小时前
第二十八章 Linux 并发与竞争实验
驱动开发·嵌入式硬件·stm32mp157
辰域电子2 小时前
STM32项目开源:实验室消防预警控制系统(代码 + 原理图 + 仿真)
stm32·单片机·嵌入式硬件·开源·proteus
szxinmai主板定制专家2 小时前
NXP LS1046A 硬件方案: LS1046A+FPGA 异构加速架构实践
大数据·图像处理·人工智能·嵌入式硬件·fpga开发
从零开始的嵌入式之旅2 小时前
day46
linux·arm开发·笔记·嵌入式硬件
老当益壮梁奶奶2 小时前
ARM汇编学习笔记(四):i.MX6ULL裸机开发:从汇编点灯到C语言BSP工程管理
c语言·arm开发·单片机·嵌入式硬件·51单片机
祖力553 小时前
ARM中断(IMX6ULL中断、GIC通用中断控制器)
嵌入式硬件·arm·imx6ull·中断·gic·通用中断控制器