I'm writing system-level code for an embedded system without memory protection (on an ARM Cortex-M1, compiling with gcc 4.3) and need to read/write directly to a memory-mapped register. So far, my code looks like this:
#define UART0 0x4000C000
#define UART0CTL (UART0 + 0x30)
volatile unsigned int *p;
p = UART0CTL;
*p &= ~1;
Is there any shorter way (shorter in code, I mean) that does not use a pointer? I looking for a way to write the actual assignment code as short as this (it would be okay if I had to use more #defines):
*(UART0CTL) &= ~1;
Anything I tried so far ended up with gcc complaining that it could not assign something to the lvalue...
Memory addresses are 32-bits long on most CPUs today, although there is a increasing trend toward 64-bit addressing). The location of i has a specific address, in this case 248,440. The pointer p holds that address once you say p = &i;.
As we already know, the size of the pointer in C is dependent only on the word size of a particular system. So, the size of a pointer to a pointer should have the usual values, that is, 2 bytes for a 16-bit machine, 4 bytes for a 32-bit machine, and 8 bytes for a 64-bit machine.
When a variable is created in C, a memory address is assigned to the variable. The memory address is the location of where the variable is stored on the computer. When we assign a value to the variable, it is stored in this memory address.
I'd like to be a nitpick: are we talking C or C++ ?
If C, I defer to Chris' answer willingly (and I'd like the C++ tag to be removed).
If C++, I advise against the use of those nasty C-Casts and #define
altogether.
The idiomatic C++ way is to use a global variable:
volatile unsigned int& UART0 = *((volatile unsigned int*)0x4000C000);
volatile unsigned int& UART0CTL = *(&UART0 + 0x0C);
I declare a typed global variable, which will obey scope rules (unlike macros).
It can be used easily (no need to use *()
) and is thus even shorter!
UART0CTL &= ~1; // no need to dereference, it's already a reference
If you want it to be pointer, then it would be:
volatile unsigned int* const UART0 = 0x4000C000; // Note the const to prevent rebinding
But what is the point of using a const
pointer that cannot be null ? This is semantically why references were created for.
#define UART0CTL ((volatile unsigned int *) (UART0 + 0x30))
:-P
Edited to add: Oh, in response to all the comments about how the question is tagged C++ as well as C, here's a C++ solution. :-P
inline unsigned volatile& uart0ctl() {
return *reinterpret_cast<unsigned volatile*>(UART0 + 0x30);
}
This can be stuck straight in a header file, just like the C-style macro, but you have to use function call syntax to invoke it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With