带gcc的裸机ARM上RAM和ROM部分之间的长_调用

带gcc的裸机ARM上RAM和ROM部分之间的长_调用,c,gcc,linker,embedded,arm,C,Gcc,Linker,Embedded,Arm,我正在使用GCC4.3开发一个ARM7TDMI项目,我很难告诉编译器在某些情况下使用长调用,而不是在其他情况下 构建过程运行arm eabi gcc为每个.c源文件生成可重新定位的ELF对象文件(最相关的CFLAG包括-Os-ffunction节-fdata节-mthumb-mthumb interwork),然后将它们全部链接到ELF可执行文件中(最相关的LDFlag包括-Wl、-gc-sections-Wl、-static-Wl、-n-nostlib和一个自定义链接器脚本)。然后,ELF文件

我正在使用GCC4.3开发一个ARM7TDMI项目,我很难告诉编译器在某些情况下使用长调用,而不是在其他情况下

构建过程运行
arm eabi gcc
为每个.c源文件生成可重新定位的ELF对象文件(最相关的CFLAG包括
-Os-ffunction节-fdata节-mthumb-mthumb interwork
),然后将它们全部链接到ELF可执行文件中(最相关的LDFlag包括
-Wl、-gc-sections-Wl、-static-Wl、-n-nostlib
和一个自定义链接器脚本)。然后,ELF文件被转换为带有
arm eabi objcopy-O binary
的原始可执行文件,自定义引导加载程序将其从ROM复制到RAM(一个包含代码和数据的SRAM)在启动时,所有内容都从RAM执行,
.rodata
存在于RAM中,所有内容都快速进行,引导后完全忽略ROM

我现在正试图改变这一点,以便某些select RO数据和select函数的文本只能存在于ROM中,并在运行时根据需要进行访问。我修改了链接器脚本,以了解两个新的部分
。.flashdata“
。.flashtext”
,两者都应该放在ROM中的固定地址。我还撒了
\uuuuuu属性((.flashdata”)
\uu属性((.flashtext”),\uuu long\u call\uuuuu))
在整个C代码中,我对构建过程进行了适当的调整,以便旧的objcopy现在添加了
-R.flashdata-R.flashtext
,我用
-j
为这些部分中的每一部分做了第二个objcopy,然后我将两个输出文件组合起来,这样引导加载程序就可以做正确的事情,ROM部分出现在e预期的内存映射位置

这一切都很好——我可以将标记为
.flashdata
部分的字符串打印出来,我可以从内存不足的代码中调用
.flashtext
函数(由于
\uuuuu long\u call\uuuuuu属性旁边的
\uuuu部分(“.flashtext”)
属性,它知道使用长调用)。该基于ROM的函数可以愉快地短调用其他基于ROM的函数,并且可以返回到其基于RAM的调用者

问题在于试图从基于ROM的函数调用到基于RAM的函数,这也必须是一个长调用。我不想在任何地方都使用长调用,所以我不想在我的CFLAGS中使用-mlong_调用。如果我将所有函数组合到一个
ROM.c
,我可以用
-mlong调用构建一个文件然而,我强烈希望避免这种情况,并将函数按用途进行分组,只需在适当的地方标记一些函数即可从ROM运行

顺便说一句,在gcc 3.4下,这是不够的。使用
-mlong调用
让编译器想到了正确的事情,但它无法完成,因为它只愿意与助手一起执行长跳转
\u call\u via\u rX
…这些调用都位于RAM中,只能通过长调用访问

因为我使用的是GCC4.3,所以现在我可以调用RAM真是太棒了。如果我可以在基于ROM的函数中标记代码,强制它使用长调用,那就更好了。有一个,但它只影响声明,所以我可以使用它而不是
\uuuuuu attribute\uuuuuuu((\uuu long\u call\uuuu))
。遗憾的是,它并没有神奇地强制编译器对有效时遇到的所有函数调用使用长调用

从组织上讲,将所有运行缓慢的代码分组到一个文件中,脱离上下文,并与一般类别中的其他代码分开,这根本不是正确的做法。请告诉我有一个选项我还没有考虑。为什么没有-fffunction节,或者只是因为代码在不同的节中(
.text
.flashtext
)自动修复我的问题


顺便说一句,当链接器发现编译器使用了一个短调用,但该调用没有留下足够的空间来管理重定位时,链接器出现的错误是:
重定位被截断以适应:R_ARM_THM_调用objs/foo.o
(由于CFLAGS中的
-f函数部分,因此使用了
.text.foo
部分代替了
.text

我怀疑没有办法自动完成您想要的操作。我有一个建议,尽管它并不完全是您想要的

声明RAM函数(比如在RAM_funcs.h中),如下所示:

int foo() RAM_CALL;
#define RAM_CALL __attribute__((__long_call__))
#include "ram_funcs.h"
然后将所有ROM函数放入它们自己的文件中,并按如下方式启动这些文件:

int foo() RAM_CALL;
#define RAM_CALL __attribute__((__long_call__))
#include "ram_funcs.h"
其他文件将使用:

#define RAM_CALL
#include "ram_funcs.h"

这并不比使用
-mlong调用
好多少,但至少它将逻辑放在函数本身附近,而不是放在一些编译选项中。例如,可以更容易地在每个.c文件中放置一些函数。

在gcc 4.3.3及更高版本中,这个问题似乎已经得到了解决,但我一直在使用4.3.2。我创建了一个不会执行的pet示例,但演示了不同部分的使用以及由此产生的链接错误。它无法使用Codesourcery进行构建,但它确实使用和更高版本进行构建。我需要更多的时间来更新整个项目以使用更新的gcc版本,因此我还不能肯定地说这解决了我的问题,但我强烈反对我想是的

另一方面,我有另一种解决方法,可以替代将所有基于ROM的函数分组为
-mthumb调用
-builded ROM.c:通过函数指针调用所有内容。在这种解决方法中,治疗比疾病更糟糕:

((void(*)(void*, void*, int))&memcpy+1)(&dest, &src, len);
你需要
+1
,这样优化器就不会比你聪明,但在我的例子中这不是问题,因为
bx
-ing到一个奇数地址表示thumb模式,我所有的代码都是thumb。但是,我不知道