5.2.6 Program Memory Symbols

Microchip PIC18 devices typically have various regions in their program memory address space in addition to the program flash memory (PFM). These regions contain device and configuration information of utility to user projects, and can be read using table reads, the same mechanism employed by the compiler to read constant data stored in PFM. The compiler defines special extern const symbols mapped to these regions in the device-specific headers. These symbols can be used by C programs to easily read the contents of these regions and are available once you include <xc.h> in your source files. The regions represented and examples symbols defined for these regions are described below.

Words in the program memory space are designated as User ID locations where the user can store checksum or other code identification numbers. These words can be programed using the #pragma config directive (see Configuration Bit Access). The following are examples of the compiler-provided symbol definitions representing user ID locations.
extern const unsigned _IDLOCs[8] __at(0x200000);
extern const unsigned _IDLOC0 __at(0x200000);
extern const unsigned _IDLOC1 __at(0x200002);
extern const unsigned _IDLOC2 __at(0x200004);
So, for example, the _IDLOC1 C variable could be used to read the second User ID location.
Configuration Words and bits allow the user to setup a device with choices of oscillators, resets, memory protection options, etc. These words can be programed using #pragma config directive. The following are examples of the compiler-provided symbol definitions representing Configuration Word locations.
extern const unsigned char _CONFIGs[10] __at(0x300000);

extern const unsigned char _CONFIG1L __at(0x300000);
typedef union {
    struct {
        unsigned FEXTOSC :3;
        unsigned :1;
        unsigned RSTOSC :3;
    };
} _CONFIG1Lbits_t;
extern const _CONFIG1Lbits_t _CONFIG1Lbits __at(0x30000);

extern const unsigned char _CONFIG1H __at(0x300001);
typedef union {
    struct {
        unsigned CLKOUTEN :1;
        unsigned PR1WAY :1; unsigned CSWEN :1;
        unsigned FCMEN :1;
    };
} _CONFIG1Hbits_t;
extern const _CONFIG1Hbits_t _CONFIG1Hbits __at(0x30001);
So, for example, the _CONFIG1Lbits.FEXTOSC bit-field could be used to read the External Oscillator Selection configuration bits.
The Device Information Area (DIA) contains information such as calibration data for the internal temperature indicator modules, stores the Microchip Unique Identifier words and the fixed voltage reference voltage, etc. The following are examples of the compiler-provided symbol definitions representing DIA locations.
extern const unsigned _DIA[32] __at(0x3F0000);
extern const unsigned _DIA_MUI[8] __at(0x3F0000);
extern const unsigned _DIA_MUI0 __at(0x3F0000);
extern const unsigned _DIA_MUI1 __at(0x3F0002);
extern const unsigned _DIA_MUI2 __at(0x3F0004);
extern const unsigned _DIA_EUI[10] __at(0x3F0010);
extern const unsigned _DIA_EUI0 __at(0x3F0010);
extern const unsigned _DIA_EUI1 __at(0x3F0012);
extern const unsigned _DIA_EUI2 __at(0x3F0014);
So, for example, the _DIA_MUI1 C variable could be used to read the second Microchip Unique Identifier.
The Device Configuration Information (DCI) holds information about the device which is useful for programming and bootloader applications. The following are examples of the compiler-provided symbol definitions representing DCI locations.
extern const unsigned _DCI[5] __at(0x3FFF00);
extern const unsigned _DCI_ERSIZ __at(0x3FFF00);
extern const unsigned _DCI_WLSIZ __at(0x3FFF02);
extern const unsigned _DCI_URSIZ __at(0x3FFF04);
extern const unsigned _DCI_EESIZ __at(0x3FFF06);
extern const unsigned _DCI_PCNT __at(0x3FFF08);
So, for example, the _DCI_WLSIZ C variable could be used to read the number of write latches per row information.
Revision ID and Device ID are unique identifiers for the device and its revision. The following are examples of the compiler-provided symbol definitions representing Revision and Device IDs.
extern const unsigned _DEVID __at(0x3FFFFE);
extern const unsigned _REVID __at(0x3FFFFC);
So, for example, the _REVID C variable could be used to read the revision ID.