用途:在资源受限设备上指导代理进行 flash 与 RAM 优化,涵盖编译器体积标志、链接器 map 分析、栈使用测量、死代码消除以及体积与速度的取舍,面向裸机与小型 RTOS 镜像。
适用时机:固件超出 flash 预算;生产环境中才出现的栈溢出;在 MCU 上选择 -Os 还是 -O2;排查意外的 .rodata 或 .bss 增长。
工作流程:
- 体积测量:使用 arm-none-eabi-size -A firmware.elf、arm-none-eabi-objdump -h firmware.elf、nm --size-sort -S firmware.elf | tail -20。
- 链接器 map:构建时加 -Wl,-Map=firmware.map,再用 grep -E '.text|.rodata|.data|.bss' firmware.map | head,找出最大符号和意外引入的库。
- 编译标志:-Os 体积优先;-ffunction-sections -fdata-sections 按符号分段;-Wl,--gc-sections 丢弃未用段;-flto 跨编译单元死代码消除;-specs=nano.specs 使用更小的 newlib(GCC ARM)。示例:CFLAGS += -Os -ffunction-sections -fdata-sections;LDFLAGS += -Wl,--gc-sections -Wl,--print-memory-usage。
- 栈分析:静态方式(用 -fstack-usage 构建后查找 *.su)或查链接器栈符号 _estack;运行时用特定模式填充栈再运行测试扫描高水位,FreeRTOS 可用 uxTaskGetStackHighWaterMark。
- RAM 分类:.bss 收缩缓冲区、使用池分配器;.data 将 const 移到 flash(转为 .rodata);堆避免 malloc、使用固定池;栈减少嵌套、缩小 ISR 栈。
- 体积与速度决策:若热路径在 ISR 或 1 kHz 循环中,该文件用 -O2(#pragma GCC optimize),否则全局 -Os。
- 代理用法示例:/resource-optimization-lowend Find top 10 flash consumers in firmware.map and suggest -gc-sections fixes。
常见问题:printf 引入 20+ KB 时改用精简 printf 并重定向 _write;--gc-sections 导致 IRQ 中断要在链接脚本用 KEEP();栈延迟溢出需测量高水位并增大 _estack;RAM 为零但 ELF 很大要检查 VMA/LMA;LTO 链接失败需确保所有目标文件使用同一 GCC 版本。
相关技能:嵌入式链接脚本、裸机启动、低功耗嵌入式、GCC 编译器、Rust no_std。以上内容来自资料,未提及的价格与平台支持暂未提供。