如何在Keil/armclang/armlink环境下将变量放置到指定内存区域?
问题原因
你当前使用的Keil自动生成的分散加载文件中,RW_IRAM1的匹配规则排在RW_IRAM2之前,二者的匹配规则都是.ANY (+RW +ZI),你自定义的段名没有显式绑定到RW_IRAM2时,链接器会优先将段分配到靠前的RW_IRAM1区域,因此之前的写法不生效。
不需要完全放弃自动生成的分散加载文件,两种可行方案如下:
方案1:使用ARM编译器内置绝对地址段规则(无需修改IDE配置)
ARMCC/ARM Clang支持特殊的段名格式.ARM.__at_<目标地址>,链接器会自动将该段分配到对应地址所属的存储区域,只要地址在你配置的RW_IRAM2范围(0x20000000 ~ 0x2001FFFF)内,就会自动归入RW_IRAM2区域。
示例代码:
// 带初始值的RW类型变量,分配到RW_IRAM2 uint32_t ram2_rw_var __attribute__((section(".ARM.__at_0x20000000"))) = 0x1234; // 零初始化的ZI类型变量,分配到RW_IRAM2 uint32_t ram2_zi_var __attribute__((section(".ARM.__at_0x20000004")));
可以用宏简化多变量定义的写法:
#define RAM2_ADDR(addr) __attribute__((section(".ARM.__at_"#addr))) uint32_t var1 RAM2_ADDR(0x20000000); uint32_t var2 RAM2_ADDR(0x20000004); uint32_t var3 RAM2_ADDR(0x20000008);
方案2:指定自定义段基址,让链接器自动分配(无需手动管理地址偏移)
如果你不想手动维护变量地址偏移,可以给自定义段统一命名,再在IDE中指定段的起始地址:
- 代码中为需要放在
RW_IRAM2的变量指定统一的自定义段名:
uint32_t in_ram2 __attribute__((section(".ram2"))); uint32_t another_ram2_var __attribute__((section(".ram2")));
- 打开Keil的
Options for Target -> Linker -> Misc controls,添加如下参数:
--section-start=.ram2=0x20000000
链接器会把所有.ram2段的内容从0x20000000开始自动分配,不会和RW_IRAM2区域内的其他内容产生地址冲突。
内容的提问来源于stack exchange,提问作者Graeme
相关产品推荐
相关产品推荐

