When accessing a hardware register in C/C++, I usually create #define
s like this:
#define HW_REGISTER ((volatile uint16_t *)0xFFFF8A00)
I.e. 0xFFFF8A00
is a pointer to a volatile uint16_t value and this value may be changed from outside so any access to *HW_REGISTER
must not be cached.
However what if the value written to the hardware register is actually a pointer? Naively we could just replace uint16_t
with uint16_t *
:
#define HW_REGISTER ((volatile uint16_t * *)0xFFFF8A00)
but I don't think that's correct. It reads 0xFFFF8A00
is a pointer to a pointer which points to volatile uint16_t data.
The correct way could be:
#define HW_REGISTER ((uint16_t *volatile *)0xFFFF8A00)
i.e. 0xFFFF8A00
is a pointer to a volatile pointer which points to non-volatile uint16_t data.
If I'm correct here, does this mean that if I want to look my #define
s consistent, I'm forced to use the swapped syntax, i.e.
#define HW_REGISTER ((uint16_t volatile *)0xFFFF8A00)
and
#define HW_REGISTER ((uint16_t *volatile *)0xFFFF8A00)
?
It's
#define HW_REGISTER ( *( uint16_t * volatile * )0xFFFF8A00 )
We read it using the spiral rule:
It's a pointer to a volatile pointer to a uint16_t.
If you're unsure, build up the type.
typedef uint16_t *HW_REGISTER_TYPE;
#define HW_REGISTER_PTR ( ( volatile HW_REGISTER_TYPE * )0xFFFF8A00 )
#define HW_REGISTER ( *HW_REGISTER_PTR )