4

Code:

static volatile unsigned char TMR0   @ 0x01;
static volatile unsigned char PORTA  @ 0x05;
static volatile unsigned char PORTB  @ 0x06;
static volatile unsigned char PORTC  @ 0x07;

This code is from the HT-PICC compiler, pic.h library file for PIC16F877A.

I understand what static volatile and other keyword means . Here the Timer0 register address is 0x01, but why they use @ in front of it? Does it have something to do with a pointer?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Electro Voyager
  • 107
  • 1
  • 8
  • 6
    It is almost certainly a notation for identifying address constants. It is not standard C; it is a non-standard extension with the compiler you're using. – Jonathan Leffler Oct 11 '18 at 06:13
  • 1
    @ takes the address of a variable in Pascal (like & in C), here it's probably some kind of compiler extension – Jakub Jůza Oct 11 '18 at 06:15
  • This question may help to answer yours: https://stackoverflow.com/questions/23737066/what-is-the-use-of-symbol-in-c-language – SethBarton Oct 11 '18 at 06:16
  • probably because converting integers to pointers usually raises warnings (because in normal C you're not supposed to hardcode the addresses) – Jean-François Fabre Oct 11 '18 at 06:37

3 Answers3

7

It's a common compiler extension in many embedded compilers, which allows you to place variable in absolute memory address.

From HI-TECH C compiler manual:

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

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

In your example:

static volatile unsigned char   TMR0    @ 0x01;

TMR0 is presumably 8-bit unsigned hardware register which exists at address 0x01.

user694733
  • 15,208
  • 2
  • 42
  • 68
4

It is an variable located at(@) a specific memory location. So there is an 8 bit variable TMR0 located at address 0x01. In the manual for the Hi-Tech C compiler for PIC see section 3.4.4 Pointer types for more information.

In vanilla C the equivalent would be:

static volatile unsigned char * TMR0 = (volatile unsigned char *) 0x01;

The @ operator is used in architectures with very low memory to help lower the memory footprint.

Gerhard
  • 6,850
  • 8
  • 51
  • 81
3

This is a common non-standard notation for allocating a variable at a specific address. In your case, it is used to map hardware registers to C variables.

Specifically, the purpose of @ is to allow a linker/debugger to use the registers as if they were objects. Meaning that you can add a watch or rw breakpoint on them in the debugger, like with any other variable.

Otherwise, if you have no need to view these in the debugger, you can use the standard C equivalent:

#define TMR0 (*(volatile uint8_t*)0x01u)

And of course, there's no need to allocate room for hardware registers, since they are already there in the hardware regardless of what the C program does.

Good debuggers come with MCU support and have the option to view MCU-specific registers in a separate window. So the main reason for using @ for registers/register maps, is because the tool chain comes with a crappy debugger. This is sadly my experience of embedded tool chains: the worse the debugger is, the messier the compiler-provided register map becomes.

But the @ notation can also be used for declaring RAM/ROM variables at specific locations. Other non-standard extensions by other compilers use various #pragma, ___declspec(section... or __attribute__(section.... Would be nice if a standard way existed, but sadly there is none.

Lundin
  • 195,001
  • 40
  • 254
  • 396