I found this header file for PIC microcontrollers by the name of pic1250.h and I'm unable to get the hang of some syntax used in it.
The source for the file is:
/*
* Header file for the Microchip
* PIC 12c508 chip
* PIC 12c509 chip
* Baseline Microcontrollers
*/
static volatile unsigned char RTCC @ 0x01;
static volatile unsigned char TMR0 @ 0x01;
static volatile unsigned char PCL @ 0x02;
static volatile unsigned char STATUS @ 0x03;
static unsigned char FSR @ 0x04;
static volatile unsigned char OSCCAL @ 0x05;
static volatile unsigned char GPIO @ 0x06;
static unsigned char control OPTION @ 0x00;
static volatile unsigned char control TRIS @ 0x06;
/* STATUS bits */
static bit GPWUF @ (unsigned)&STATUS*8+7;
static bit PA0 @ (unsigned)&STATUS*8+5;
static bit TO @ (unsigned)&STATUS*8+4;
static bit PD @ (unsigned)&STATUS*8+3;
static bit ZERO @ (unsigned)&STATUS*8+2;
static bit DC @ (unsigned)&STATUS*8+1;
static bit CARRY @ (unsigned)&STATUS*8+0;
/* OPTION bits */
#define GPWU (1<<7)
#define GPPU (1<<6)
#define T0CS (1<<5)
#define T0SE (1<<4)
#define PSA (1<<3)
#define PS2 (1<<2)
#define PS1 (1<<1)
#define PS0 (1<<0)
/* OSCCAL bits */
static bit CAL7 @ (unsigned)&OSCCAL*8+7;
static bit CAL6 @ (unsigned)&OSCCAL*8+6;
static bit CAL5 @ (unsigned)&OSCCAL*8+5;
static bit CAL4 @ (unsigned)&OSCCAL*8+4;
/* GPIO bits */
static bit GP5 @ (unsigned)&GPIO*8+5;
static bit GP4 @ (unsigned)&GPIO*8+4;
static bit GP3 @ (unsigned)&GPIO*8+3;
static bit GP2 @ (unsigned)&GPIO*8+2;
static bit GP1 @ (unsigned)&GPIO*8+1;
static bit GP0 @ (unsigned)&GPIO*8+0;
#define CONFIG_ADDR 0xFFF
#define FOSC0 0x01
#define FOSC1 0x02
#define WDTE 0x04
#define CP 0x08
#define MCLRE 0x0F
I'm unable to understand the whole modifer-datatype @ declaration-something. Can someone please help me out? I'm just a newbie at this.
It's a compiler extension.
From PIC MPLAB XC8 compiler documentation (emphasis mine):
5.5.4 Absolute Variables
Most variables can be located at an absolute address by following its declaration with
the construct @ address, where address is the location in memory where the
variable is to be positioned. Such a variables is known as an absolute variables.
5.5.4.1 ABSOLUTE VARIABLES IN DATA MEMORY
Absolute variables are primarily intended for equating the address of a C identifier with
a special function register, but can be used to place ordinary variables at an absolute
address in data memory.
For example:
volatile unsigned char Portvar @ 0x06;
will declare a variable called Portvar located at 06h in the data memory. The compiler
will reserve storage for this object (if the address falls into general-purpose RAM) and
will equate the variable’s identifier to that address.
Note that MPLAB XC8 is not the only compiler to have the same @
construct to place an object in the specific memory location.
Another well known compiler is Freescale CodeWarrior (at least for HCS08).
Another one is IAR C Compiler (at least for MSP430 and AVR).
It's an extension in the PIC compiler, to place a variable at a specific memory position. No other compiler I know have that extension.
It's a C language extension supported by the PIC compiler that allows assigning variables to specific RAM addresses.
exemples:
char a @ 0x25; /* place A at address 0x25 */
bit b @ 0x25.3; /* place B at the third bit of address 0x25 */
There are three uses for this:
- In embedded system you often have very little memory and need to pack several variables in the same byte. This syntax makes it easier, although a standard bit field
would work too.
- Another reason is that PIC registers are mapped to RAM, so that you can access them like any other memory location. With this syntax you can define synonyms for the bits you are interested in and use them like normal variables.
- Put you own variable (regardless of size) at a specific location. This is occasionally useful.
Remember that embedded programming is all about total control of the hardware.
In addition to what has already been said, please note that the non-standard @
operator is a superfluous feature. You can achieve exactly the same behavior with standard C:
#define RTCC (*(volatile uint8_t*)0x0001u)
Since the variables in this case are hardware registers, you don't need to worry about allocation, they are already present in the hardware. If you want to allocate a variable at a custom address, there should be a linker file of some kind to fix that (since the @ operator only solves specific allocation for variables, not for code).
The main reason why many embedded compilers come up with some non-standard operator like @
is because they can't think outside the box when designing the debugger. They expect some sort of variable to be present in the object file which is fed to the debugger, but if you use #define, no such "debug information object" is allocated.
If the debugger looked at the source code instead, or better yet, had MCU awareness built-in, then non-standard code like this wouldn't be necessary. High quality tools from companies that focus solely on debuggers always come with built-in support for viewing register maps.