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.