ltc E121: relocation error in "task1": relocation value 0xd0005000, type abs18 space, offset 0x2, section ".text.file_2.func" at
address 0x8000036c is not a valid address in R_TRICORE_18ABS. Hint: check the mapfile for a section that occupies this address.
Another variant:
ltc E121: relocation error in "task1": relocation value 0xd0005000, type R_TRICORE_16SM, offset 0x0, section ".text.file_2.func" at
address 0x8000036c is not within a 16-bit signed range from the value of A0 as defined by the symbol _SMALL_DATA_
In the TriCore CPU, near-addressable data must be located within the first 16 kB of a 256 MB segment (offset 0x0 to 0x00003FFF within a segment).
The E121 error occurs when a variable is defined as a far-addressable variable, but an extern declaration is made for a near-addressable variable instead. Then the linker may place the variable anywhere in memory. In the C modules where the variable is declared extern, a near access is made, which requires that the variable be placed within the first 16 kB.
Example:
/* file_1.c */
void func(void);
__far char var_1 __at(0xD0005000); /* __at is used to ensure the variable is placed outside of the near addressable range */
int main (void)
{
func();
return 0;
}
/* file_2.c */
extern __near char var_1; /* __near is used, while it should have been __far */
void func(void)
{
var_1 = 10;
}
cctc file_1.c file_2.c -o result.elf -t -v -s
Generated linker error:
ltc E121: relocation error in "task1": relocation value 0xd0005000, type abs18 space, offset 0x2, section ".text.file_2.func" at
address 0x8000036c is not a valid address in R_TRICORE_18ABS. Hint: check the mapfile for a section that occupies this address.
Although the error in the example above is obvious, the problem can also be hidden. This applies when different default-near-size options are used (C compiler option -N). This option is used to specify the maximum size of a data object for automatic near allocation. The default value is 8, which means that all data with a size smaller than or equal to 8 bytes is near-addressed and, as a result, must be located in a near-addressable memory range.
The problematic situation shows up when the C source file wherein the variable is defined is, for example, compiled using the option -N0. This forces the compiler to access all data that is not explicitly defined/declared using a __near qualifier using a far addressing mode. When the C source files, which include the 'extern' declarations for that variable, are compiled using the option -N8 (or the option is not used at all, which is equal to using -N8), then the access to the variable will be a near access.
Modified example:
/* file_1.c */
void func(void);
char var_1 __at(0xD0005000); /* __at is used to ensure the variable is placed
outside of the near addressable range */
int main (void)
{
func();
return 0;
}
/* file_2.c */
extern char var_1;
void func(void)
{
var_1 = 10;
}
cctc file_1.c -o file_1.o -N0 -t -v -s -co
cctc file_2.c file_1.o -o result.elf -N8 -t -v -s
Here __near and __far are not used in the source code, but the problem is the same due to the different default near size values used with the -N option.
This kind of E121 error can also show up when, instead of a near/far address mixture, a different, non-far address method like A0, A1, A8, or A9 addressing is used. Using the address register, indexed access requires the data to be located within +/- 32 kB of the address the address register points to. For example, when the A0 register content is 0xD0018000, then the address range where all A0-addressed variables must be placed in is 0xD0010000 to 0xD001FFFF. When an A0 access is made to a variable placed outside of the range, the linker error E121 is generated:
ltc E121: relocation error in "task1": relocation value 0xd0005000, type R_TRICORE_16SM, offset 0x0, section ".text.file_2.func" at
address 0x8000036c is not within a 16-bit signed range from the value of A0 as defined by the symbol _SMALL_DATA_
The linker will ensure a correct placement of the address register accessed variables within the 64kB range, if the __aX (__a0, __a1, __a8, __a9) memory qualifier is used for the variable definition as well as the extern declaration.
Match __near, __far and __aX between:
Compile all modules with the same -N value, and avoid mixing:
It is possible to overrule the -N option locally using a pragma. E.g.:
#pragma for_extern_data_use_memory __far
Then all extern declared variables following that pragma will be far accessed, independent of the -N value used.
After applying one of the solutions, the E121 relocation error disappears.
1. Rebuild the project.
2. Confirm the E121 linker error is no longer reported.