13.3 Representation of Constants in Program Memory
When constants are allocated in program memory, or any variable is defined with the
space(psv)
attribute, the linker calculates two different memory
addresses for the object:
- The virtual address is a 16-bit data memory address. This address is used by the microcontroller to access the constant data at run time. The virtual address always falls within the memory range associated with the Program Space Visibility (PSV) window.
- The load address is a 24-bit program memory address. This address is used by the linker to specify where the constant data is stored in non-volatile memory. The load address can be anywhere in the program memory space.
The load address in program memory is always unique. However, the virtual address in data memory might not be, especially in a large application when constant arrays are defined with managed PSV access. Both kinds of address are displayed in the link map.
Consider this example, which declares two constant arrays:
#include <stdio.h>
const int table1[] = {0, 1, 2, 3, 4};
const int table2[] = {5, 6, 7, 8, 9};
int main(void)
{
const int *data_addr;
long load_addr;
data_addr = &table2[0];
load_addr = __builtin_tbladdress(table2);
printf ("Virtual address of table2: 0x%x\n", data_addr);
printf ("Load address of table2: 0x%lx\n", load_addr);
}
The address of table2
appears three times in the link map:
- In a list of program memory symbols sorted by address.
- In a list of program memory symbols sorted by name.
- In a representation of the section map, as shown below.
The section map representation begins with the name of the output section, along with its virtual address, length, and load address. On the next line is the name of the input section, along with its virtual address, length, and the object file which defined it (most often a temporary file). On subsequent lines are the virtual address and name of symbols defined within that input section. It’s worth noting that section names appear on the left side of this representation, while symbol names appear on the right side.
.const 0x9050 0x58 load address 0x001050
.const 0x9050 0x58 /tmp/ccCIQdIb.o
0x9050 _table1
0x905a _table2