【发布时间】:2019-03-09 07:53:34
【问题描述】:
我正在使用 NXP 的 I.MXRT 系列 Cortex-M7 芯片开发嵌入式系统。我需要在 RAM(ITCM) 中重定位一些 C 函数,而不是在 Flash 中。 ITCM 的地址从 0x00000000 开始,Flash 从 0x60000000 开始。因此,位于 Flash 的函数调用位于 ITCM 的函数将执行长分支。但它得到一个编译错误
(.ARM.exidx.itcm.text+0x0):重定位被截断以适应:R_ARM_PREL31 针对 `.itcm.text'
这是我的代码
__attribute__ ((long_call,section(".itcm.text"),noinline))
int foo(int k)
{
return k + 1;
}
我的链接脚本
MEMORY
{
/*
* SPI Flash
*
*
*/
ITCM(xrw) : ORIGIN = 0x00000000, LENGTH = 128K
DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20200000, LENGTH = 256K
FLASH (rx) : ORIGIN = 0x60000000, LENGTH = 4096K
}
/*************omit***************/
_siitcm = LOADADDR(.itcm.text);
.itcm.text : ALIGN(4)
{
__itcm_start__ = .;
*(.itcm.text .itcm.text.*)
. = ALIGN(4);
__itcm_end__ = .;
} >ITCM AT>FLASH
编译器标志是
arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb ${FP_FLAGS} -std=c++11 -O3 -munaligned-access -ffunction-sections -fdata-sections -ffreestanding
链接器标志是
"arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb ${FP_FLAGS} -std=c++11 -O3 -munaligned-access -ffunction-sections -fdata-sections -ffreestanding -T ${ MEM_LD_FILE} -T ${LIBS_LD_FILE} -T ${SECTIONS_LD_FILE} -nostartfiles -Xlinker -gc-sections -u _printf_float -Wl,-Map=${TARGET_MAP} --specs=nano.specs"
当分支地址大于0x40000000时似乎会发生错误。那么,如何解决这个问题呢?
/* 第二版 */
我通过添加编译器标志 -fno-exceptions 解决了这个问题。但是不知道为什么?
【问题讨论】:
-
使用彼此靠近的虚假地址,构建它,查看它使用的地址和说明,这应该可以解释它。
-
或者实际上只是查看目标文件,因为它无法链接它...
-
您可以从Exception Handling ABI for the ARM Architecture (ARM IHI 0038B) 中获得一些关于
-fno-exceptions行为的见解,特别是第4.4.2 节“重定位”,其中提到了使用R_ARM_PREL31进行偏移。R_ARM_PREL31是 31 位 2 的补码 - 注意:不是 32 位数字。见ELF for the ARM Architecture (ARM IHI 0044E) -
如果您将进入 RAM(ITCM) 的 C 函数编译为 C 而不是 C++,也许会有所帮助?
-
嗯,31位2的补码的跳转地址确实是+- 0x40000000。但它应该使用一个长分支指令 BLX Ri,它可以根据 ARM 的手册跳转所有 32 位地址空间。其实我也不清楚什么是“搬家”?我的项目包含 C 和 C++ 文件。进入 ITCM 的函数位于外部“C”块中。但我认为链接器是 C++。