I'm writing an application on top of an Altera soft processor. The API provides access to registers, defined in VHDL, as shown below.
#define __IO_CALC_ADDRESS_DYNAMIC(BASE, OFFSET) \
((void *)(((alt_u8*)BASE) + (OFFSET)))
#define IOWR_32DIRECT(BASE, OFFSET, DATA) \
__builtin_stwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
Based on everything I've learned about writing code that interfaces with hardware or registers directly, I've written my code like this,
typedef uint8_t volatile reg; /* special type to access registers */
typedef struct reg_one /* access to base and offsets */
{
reg data_0; /* first 8 bits */
reg data_1; /* second 8 bits */
.
.
} reg_one;
static reg_one *const reg_ptr = (reg_one *)SOME_BASE_ADDRESS;
uint32_t data;
data = 0;
__builtin_stwio(&(reg_ptr->data_0), data);
However, the address is cast to a void * and the volatile and const qualifiers are immediately discarded. Is there a work around for this, or am I just missing something simple?
I understand that using a macro to define a pointer is an option,
#define reg_ptr ((reg_one *)SOME_ADDRESS)
but I'd prefer to use a constant object for scope and type.
Thank you for any help in advance!