我正在使用gcc来为ARM Cortex-M4F微控制器编译一些代码。我的应用程序使用了我已经方便地写入C文件的大量数据:大量的int和float数组,指向这些各种数组的圆形链接列表,各种结构等等。
当我编译它时,它总共增加了大约500K的数据,再加上实际应用的数百K。 gcc将所有这些数据方便地放入.data节中;然后,ld尝试构建将.data节放入RAM并将.text(代码)节放入FLASH的小精灵。我使用的MCU没有500K RAM,因此无法构建ELF,但确实具有1M FLASH。我试图更改链接程序脚本,以便将.data和.text都放入“工作”的FLASH中,但是还有其他一些代码期望它的数据进入RAM,因此最终执行失败;我无法做出彻底改变。
[我需要告诉gcc将C文件中的每个对象放入.text部分,以便它可以与其余的非可变内容一起进入FLASH,或者至少可以指示其他部分我的链接描述文件该怎么做,以免干扰内存中没有问题的现有Blob。我不知道该怎么做。这是我所拥有的一个非常精简的例子
/* data.c */
static char* option_array_0_0[] =
{
"O=0.40",
"K=FOO",
"JAR=JAR",
};
static int width_array_0_0[] =
{
0,
1,
1,
};
Window window_array_0[] =
{
{
option_array,
width_array,
},
};
/* main.c */
extern Window window_array_0[];
int main()
{
/* Do stuff */
}
data.c,window_array_0中的内容以及与其链接的所有内容(或大多数内容,可能是字符串数组将进入.text?)都放在了.data中,我的链接描述文件放入了RAM中。我希望将其全部放在不同的部分,然后将其放入闪存中。那里有成千上万种此类数组,外加数百种结构和数十种其他信息。这可能改变吗?作为测试,我用char [500000]随机数据替换了我的“ window_array_0”,并且在编译过程中没有抱怨,所以我假设将其全部放入.text中(如预期的那样),我只是不知道如何制作对任意对象执行此操作。感谢您的帮助。
大多数编译器/链接器,如果将变量声明为static const
,它将把它放在文本部分而不是数据中。显然,这些必须预先初始化并且不能在运行时进行修改,但这是在Flash中有意义的唯一方法。
正如其他评论者所指出的那样,“静态常量”项通常以.rodata节结尾,该节很可能被放置在潜在只读存储器中的.text旁边。需要注意的是,根据您的情况,它可能是正确的,也可能不是正确的,因为它特定于特定的目标,并且可能会因特定的构建过程而改变(即,链接器选项,在C代码中通过__attribute__((section("name")))
指定的特定部分,链接器脚本,已调整的二进制文件用各种binutils等构建之后)。
如果需要精确控制内存中的布局,并且知道自己在做什么,则可以使用LD script来完成。除了其他功能外,它还可以指定文件data.o中的.rodata应该放在链接到可执行文件的所有其他.o文件中.text之前/之后。
您可以使用arm-<your toolchain variant>-ld -verbose
转储默认的链接程序脚本并将其用作调整的起点。
IIRC,闪存中的代码通常要求为ROPI(与位置无关的只读)。因此option_array_0_0
和width_array_0_0
将需要const
限定符(只读)。但是:
Window window_array_0[] =
{
{
option_array,
width_array,
},
};
需要以某种方式更改(我假设option_array
和width_array
确实是数组)。这使得window_array_0
不独立于位置。
所有非平凡的嵌入式项目均应具有linker script。它定义了将不同的符号(函数,全局变量,调试符号等)放置在内存中的位置。这是有关gcc linker script的一些教程。
强制all数据放在一个部分中可能不是最佳解决方案!
NOTE:由于这些数组是NOT常量,因此将它们存储在data节中没有任何意义!因为这意味着您最终将通过代码覆盖代码段(这是PRETTY危险)。使它们成为const
或创建一个未由加载程序初始化的no-init
节,然后在重置时对其进行初始化。
在代码中的某个地方(.text部分)像样本一样放置:
__attribute__((section(".text")))
const int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};
或如果要更改变量,则不带const:
__attribute__((section(".text")))
int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};
然后尝试更改它:
test[0] = 0xffffffff;
这可在我的Linux 32 intel机器上使用。