SPNU118Z September 1995 – March 2023 66AK2E05 , 66AK2H06 , 66AK2H12 , 66AK2H14 , AM1705 , AM1707 , AM1802 , AM1806 , AM1808 , AM1810 , AM5K2E04 , OMAP-L132 , OMAP-L137 , OMAP-L138 , SM470R1B1M-HT , TMS470R1A288 , TMS470R1A384 , TMS470R1A64 , TMS470R1B1M , TMS470R1B512 , TMS470R1B768
When you declare a variable such as
int x = 1234;
in C/C++, an object with the identifier (name)
“x” is created at address &x with the contents 1234. In addition, a related
linker symbol named x
is created. That linker symbol represents
just the address, not the object itself. References to the linker symbol
x
result in the linker symbol’s value, which is the address.
However, references to the C/C++ identifier x
result in the
contents 1234. If you want the address of this C/C++ identifier, you need to use
&x
. Thus, the C/C++ expression &x
has
the same value as the linker expression x
, although the linker
symbol does not have an associated type.
Suppose a linker-defined symbol represents an integer rather than an address, such as __TI_STACK_SIZE. There is no way to refer to an integer linker symbol directly in the compiler, so we use a trick. First, pretend this linker symbol represents an address. Declare a fake variable with the same name in the C/C++ code. Now, refer to &__TI_STACK_SIZE, an expression that has the same value as the linker symbol __TI_STACK_SIZE. The value does have the wrong type, which you can change with a cast as follows:
extern unsigned char __TI_STACK_SIZE;
size_t stack_size = (size_t) &__TI_STACK_SIZE;
Leaving out _symval as shown in the above example works most of the time, but not always. In some cases, a pointer value is not adequate to represent a linker symbol value. For example, some targets have a 16-bit address space and thus 16-bit pointers. TI linker symbols are 32 bits, so a linker symbol can have a value that is larger than can be represented by a target pointer. In such cases, the expression &v reflects only the lower 16 bits of the actual value of the linker symbol “v”. To get around this problem, use the _symval built-in operator, which causes all of the value bits of the linker symbol to be copied:
extern void v;
unsigned long value = (unsigned long)_symval(&v);
For every kind of linker symbol, use this pattern:
extern void name;
desired_type name = (desired_type)_symval(&name);
For example,
extern void farfunc;
void foo()
{
void (*func)(void) = (void (*)(void))_symval(&farfunc);
func();
}