28

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.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
Avi Gabhawala
  • 291
  • 3
  • 5
  • 1
    What compiler are you using? – FatalError Apr 11 '13 at 18:11
  • 13
    It's not standard C. `@` is not part of the execution character set (it hadn't yet been added to ASCII when C was created). – luser droog Apr 11 '13 at 18:12
  • 1
    This is something like assigning aliases to memory addresses. – Eddy_Em Apr 11 '13 at 18:13
  • 3
    Pics have a few special compilers. While they are written in C, they do have a lot of special functions due to the fact that they are such low level devices. This looks like a header file made by microchip to aid in the development. What this syntax will allow you to do is use the . operator to access individual bits in an address bytes. For instance this can be seen when you do `PORTAbits.RA4 = 0;` The @ sign is mapping the bit to the proper bytes (registers). – Reid Apr 11 '13 at 18:30
  • Don't feel bad -- no one really understands C syntax. They just get "maze bright" for some subset and stick with it. – Hot Licks Apr 11 '13 at 18:42
  • @HotLicks That may be too strongly stated. On the other hand taking a pre-test for a job interview the other day I encountered a questions about `const volatile` declarations and had to ask the web to get the correct interpretation. – dmckee --- ex-moderator kitten Apr 11 '13 at 20:10
  • 1
    You probably don't have to use this syntax use the PIC registers, because they ahve pre-defined every imaginable one. It's pretty darn self explanatory. `static volatile unsigned char RTCC @ 0x01`. "The RTCC register is AT address 1". This is a no brainer that you can understand from the header file, without a reference manual. – Kaz Apr 12 '13 at 03:03
  • @Kaz: Well, yeah but I couldn't notice it until you guys pointed this out! Thanks for the answers everyone! – Avi Gabhawala Apr 12 '13 at 06:29
  • @luser droog - The @ character was included in the first revision of ASCII [ASA X3.4-1963](https://worldpowersystems.com/ARCHIVE/codes/X3.4-1963/page5.JPG), almost 10 years before the creation of C. – Jeremy Jun 27 '19 at 11:39
  • @Jeremy True, but it's missing from the [second (1965) revision](https://en.wikipedia.org/wiki/ASCII#Printable_characters). And it was this version that was in the PDP-7 hardware which was C's first target. – luser droog Jun 27 '19 at 13:43
  • @luser droog - That Wikipedia article shows that the 'approved but unpublished' 1965 revision did indeed include '@', but at a different code (140 vs 64). Having said that, I can perfectly understand a manufacturer or language developer, seeing the instability of the character set coding standard, avoiding the problematic code points entirely. – Jeremy Jun 28 '19 at 07:37

4 Answers4

39

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).

ouah
  • 142,963
  • 15
  • 272
  • 331
22

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.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • how its useful to put a variable at specific memory can you explain bit more. Is it not like low level language? – Grijesh Chauhan Apr 11 '13 at 18:25
  • 11
    When working directly with hardware, especially microcontrollers or embedded stuff, putting things at specific address can be *very* useful. The system may read or write to a particular address (in this case, those status bits probably come from some hardware input). – ssube Apr 11 '13 at 18:28
  • 1
    @GrijeshChauhan Look closely at how CPUs are organized. Some of them have special registers at predefined memory locations. Yes, registers in the memory address space. What you're seeing in the question reflects that. – Alexey Frunze Apr 11 '13 at 18:28
  • @GrijeshChauhan It will make it easier to make variables for special hardware register and their flags. – Some programmer dude Apr 11 '13 at 18:28
  • @JoachimPileborg Thanks! it also reminds me,I used to write on VDU memories directly to implement my own printf in DOS in college in time. – Grijesh Chauhan Apr 11 '13 at 18:34
  • @AlexeyFrunze *Registers in the memory address space*. Is it? confusion..need a link..:( – Grijesh Chauhan Apr 11 '13 at 18:35
  • 1
    @GrijeshChauhan Download [TMS320C54x DSP Reference Set Volume 1: CPU and Peripherals - SPRU131G.pdf](http://www.ti.com/litv/pdf/spru131g) and look up in it "memory-mapped" and see table "Table 3–3. CPU Memory-Mapped Registers". It's just one CPU example. There are others with memory-mapped registers. – Alexey Frunze Apr 11 '13 at 19:05
  • @GrijeshChauhan From a higher level perspective it's memory mapped IO but with the addresses baked into the hardware as opposed to the OS and device selecting locations at runtime. – Dan Is Fiddling By Firelight Apr 11 '13 at 20:49
  • It's quite common for microcontroller compilers. Most AVR compilers I know also support this. – vsz Apr 12 '13 at 03:35
6

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

A short extension:

This is no longer working since xc8 2.0 and up. You now had to write:

unsigned char a __at(0x025);

to put a variable (a) at an absolute address (0x025).

With XC8 2.0 it is possible to compile your old code using the @ syntax if you set the compiler settings to use "C90" format. The setting looks like this, it is under "XC8 Global Options" and is called "C standard".

Mike
  • 4,041
  • 6
  • 20
  • 37