以下仅仅是本人的学习笔记,可能存在错误,欢迎指正
ARMCC
-
使用
__attribute__((section("section name")))
例如:/*当“testvar”存在时,变量var会被添加到段,若不存在,则会创建段“testvar”,并添加变量var*/ int var __attribute__((section("testvar"))) = 0; int var __attribute__((section("testvar"))) = 0;
如果不使用sct文件指定输出段,则变量会根据
const
修饰符来决定最终的输出段 -
在
sct文件
指定输入段的输出段LR_ROM1 0x80000000 0x000C0000 { ADDER 0x80000000 { file.o (testvar) } }
如果指定了输出段,则文件内的所有使用__attribute__((section(“testvar”)))修饰的变量都将添加到该输出段,这个操作是强制的,即使没有
const
修饰,变量依然会被添加到RO段更加详细的信息可以看keil_armlink_user_guide的7.2.5节,keil_armlink_user_guide文档keil自带。
-
如果想获得段起始地址则可以这样操作。
/*链接器链接时会为段生成几种符号,符号不占物理空间,仅仅代表地址*/ extern const int testvar$$Base;/*符号section_name$$Base在段起始地址*/ extern const int testvar$$Limit;/*符号section_name$$Limit在段结束地址*/ printf("%p",&testvar$$Base); printf("%p",&testvar$$Limit);
ARM-GCC
- 与ARMCC相同,使用
__attribute__((section("section name")))
指定输入段,但不同的是,链接器不会自动将自定义段添加到输出段,因此,如果不在lds
文件中指定输出段,则该输入段和指向该段的变量都将被弃用。 - 标明自定义输入段的输入段方式如下:
SECTIONS { .text : { __ftability_start = .; KEEP(*(section name)) __ftability_end = .; } }
__ftability_start与__ftability_end是符号声明,与
section_name$$Base
和section_name$$Limit
作用相同,因为ARM-GCC的链接器不会自己生成,所以需要在链接文件中声明
小结
- 对于ARMCC,仅仅在代码中声明符号却不引用的话,map文件中不会记录该符号,更有可能将该输入段与指定到该段的变量丢弃(与是否使用used修饰有关),但是ARM-GCC直接将符号定义在链接文件中,无论文件中是否引用该符号都会被map文件记录。
- rtthread中大量使用了这种方式来实现他们的初始化机制。