Hyz Yuzhou
Hyz Yuzhou

Reputation: 83

ARM Cortex-M7 long branch get error "relocation truncated to fit: R_ARM_PREL31" at compiling time

I'm developing an embedded system with NXP's I.MXRT Series Cortex-M7 chip. I need relocation some C function in RAM(ITCM) while not in Flash. Address of ITCM begin at 0x00000000, Flash begin at 0x60000000. So a function locating at Flash call a function locating at ITCM will perform a long branch. But It gets a compiling error

(.ARM.exidx.itcm.text+0x0): relocation truncated to fit: R_ARM_PREL31 against `.itcm.text'

Here is my code

__attribute__ ((long_call,section(".itcm.text"),noinline))
int foo(int k)
{
     return k + 1;
}

My linkscript

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

Compiler flags are

arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb ${FP_FLAGS} -std=c++11 -O3 -munaligned-access -ffunction-sections -fdata-sections -ffreestanding

Linker flags are

"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"

It seems the error occurs when branch address is greater than 0x40000000. So, how to fix this issue?

/* Second Edition */

I have solved the issue by adding a compiler flag -fno-exceptions. But I don't know why?

Upvotes: 0

Views: 2134

Answers (1)

raver dave
raver dave

Reputation: 21

The ARM-EABI specifies exceptions veneers are 31bit relative. Meaning that all C++ that can throw or catch (ie., that with C++ linkage, not -fno-exception) will need to be located in memory no more than 30 bits (plus or minus) from the .ARM-extab and .ARM.exidx sections or the relative offset will be insufficient -- thus the error.

It is likely the ARM-EABI took advantage of the Linux default user space being the lower 31 bits of the 32 bits of the ARM32 address space.

So, look at your memory map. Is there a stash +-30 bits to place the extab/exidx for greatest coverage of your .text memory (XIP flash, SDRAM, OCRAM)? Can you restrict (via the linker script) your C++ to just the covered regions? Can you place non-text (data, bss, etc.) in the out of range memory? (Data and non-C++ and C++-noexception .text accesses are not REL31 -- just C++ exceptions are.)

Upvotes: 2

Related Questions