Yes, that's basically it, other than the extraneous &
operator in your example. You simply create a pointer which points to a specific address and then you can read or write via that pointer.
Of course, it's not portable but, since you're in embedded space, that's not so much of an issue.
What you tend to see is a header file containing the various addresses specified as you have:
// Bit masks for control, and control/data locations.
#define UART_CTRL_READREADY 0x01
#define UART_CTRL_WRITREADY 0x01
#define UART_CTRL (*((unsigned char *)(0xcafebabe)))
#define UART_DATA_READ (*((unsigned char *)(0xdeadbeef)))
#define UART_DATA_WRIT (*((unsigned char *)(0xca11ab1e)))
(and the volatile
keyword may come in handy here) so that you can simply code up:
// Wait for data to become available.
while (!(UART_CTRL & UART_CTRL_READREADY))
;
// Get it then clear flag for next byte
databyte = UART_DATA_READ;
UART_CTRL &= ~UART_CTRL_READREADY;
Of course, you may also consider hiding the complexity inside functions so that you can change it without much impact. Things like:
int getFlag (char *location, unsigned char mask);
void setFlag (char *location, unsifgned char mask, int setFlag);
unsigned char getData (char *location);
Although this may be slower, it will greatly ease your task if you ever need to change the code.
In terms of pointers on low-level coding like this, it's no different to "regular" coding in C. You'll probably want to read up on bitwise operators since some low level devices may require that level of manipulation.