Data items can be assigned an absolute address with the at <address> keyword, in addition to a storage class, e.g.:
xdata at 0x7ffe unsigned int chksum;In the above example the variable chksum will located at 0x7ffe and 0x7fff of the external ram. The compiler does not actually reserve any space for variables declared in this way (they are implemented with an equate in the assembler). Thus it is left to the programmer to make sure there are no overlaps with other variables that are declared without the absolute address. The assembler listing file (.lst) and the linker output files (.rst) and (.map) are good places to look for such overlaps.
In case of memory mapped I/O devices the keyword volatile should be used to tell the compiler that accesses might not be optimized away:
volatile xdata at 0x8000 unsigned char PORTA_8255;Absolute address can be specified for variables in all storage classes, e.g.:
bit at 0x02 bvar;The above example will allocate the variable at offset 0x02 in the bit-addressable space. There is no real advantage to assigning absolute addresses to variables in this manner, unless you want strict control over all the variables allocated. One possible use would be to write hardware portable code. For example, if you have a routine that uses one or more of the microcontroller I/O pins, and such pins are different for two different hardwares, you can declare the I/O pins in your routine using:
extern volatile bit SDI;Then, someplace in the code for the first hardware you would use
extern volatile bit SCLK;
extern volatile bit CPOL;
void DS1306_put(unsigned char value)
{
unsigned char mask=0x80;
while(mask)
{
SDI=(value & mask)?1:0;
SCLK=!CPOL;
SCLK=CPOL;
mask/=2;
}
}
bit at 0x80 SDI; /* I/O port 0, bit 0 */Similarly, for the second hardware you would use
bit at 0x81 SCLK; /* I/O port 0, bit 1 */
bit CPOL; /* This is a variable, let the linker allocate this one */
bit at 0x83 SDI; /* I/O port 0, bit 3 */and you can use the same hardware dependent routine without changes, as for example in a library. This is somehow similar to sbit, but only one absolute address has to be specified in the whole project.
bit at 0x91 SCLK; /* I/O port 1, bit 1 */
bit CPOL; /* This is a variable, let the linker allocate this one */