将C文件中的所有数据强制置于.text(或其他)部分中

问题描述 投票:2回答:5

我正在使用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中(如预期的那样),我只是不知道如何制作对任意对象执行此操作。感谢您的帮助。

c gcc linker microcontroller ld
5个回答
1
投票

大多数编译器/链接器,如果将变量声明为static const,它将把它放在文本部分而不是数据中。显然,这些必须预先初始化并且不能在运行时进行修改,但这是在Flash中有意义的唯一方法。


2
投票

正如其他评论者所指出的那样,“静态常量”项通常以.rodata节结尾,该节很可能被放置在潜在只读存储器中的.text旁边。需要注意的是,根据您的情况,它可能是正确的,也可能不是正确的,因为它特定于特定的目标,并且可能会因特定的构建过程而改变(即,链接器选项,在C代码中通过__attribute__((section("name")))指定的特定部分,链接器脚本,已调整的二进制文件用各种binutils等构建之后)。

如果需要精确控制内存中的布局,并且知道自己在做什么,则可以使用LD script来完成。除了其他功能外,它还可以指定文件data.o中的.rodata应该放在链接到可执行文件的所有其他.o文件中.text之前/之后。

您可以使用arm-<your toolchain variant>-ld -verbose转储默认的链接程序脚本并将其用作调整的起点。


1
投票

IIRC,闪存中的代码通常要求为ROPI(与位置无关的只读)。因此option_array_0_0width_array_0_0将需要const限定符(只读)。但是:

Window window_array_0[] =
{
    {
        option_array,
        width_array,
    },
};

需要以某种方式更改(我假设option_arraywidth_array确实是数组)。这使得window_array_0不独立于位置。


0
投票

所有非平凡的嵌入式项目均应具有linker script。它定义了将不同的符号(函数,全局变量,调试符号等)放置在内存中的位置。这是有关gcc linker script的一些教程。

强制all数据放在一个部分中可能不是最佳解决方案!

NOTE:由于这些数组是NOT常量,因此将它们存储在data节中没有任何意义!因为这意味着您最终将通过代码覆盖代码段(这是PRETTY危险)。使它们成为const或创建一个未由加载程序初始化的no-init节,然后在重置时对其进行初始化。


0
投票

在代码中的某个地方(.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机器上使用。

© www.soinside.com 2019 - 2024. All rights reserved.