Reputation: 1
I am learning how to code for ARM A9 under Linux. Right now I access some peripherals like LEDS. My code is actually working, but partly based on a tutorial. The only one part I don't understand is:
void *virtual_base;
void *led_addr;
void *sw_addr;
int fd;
int switches;
switches=*(uint32_t *)sw_addr;
`
The part I don't understand is why do I have to write
*(uint32_t *)sw_addr;
*sw_addr
means it is a variable, which points to a specific address.In my case it points to specific peripheral register.Reading from this address will read the status of switches on my board.
But what
*(uint32_t *)sw_addr
means? How do you interpret it?
Why I just cant write
switches= sw_addr
?
I am bit confused , as you can see.
Upvotes: 0
Views: 94
Reputation: 4368
The "for dummies" answer:
*(uint32_t *)sw_addr means?
It means, give me uint32_t
worth of data (32 bits) from where sw_addr
points to.
How do you interpret it?
void *sw_addr
points to something of unknown size, it's a void pointer
. Casting it to a uint32_t
pointer tells us it points to a 32bit unsigned integer
. Then when we want the data, we get 32 bits
(assuming all casts are correct and can be made).
Why I just cant write switches= sw_addr?
Assuming you mean switches = *sw_addr
, it's because it's like saying: Give me unknown amount of data from pointer sw_addr
(we don't know the type its pointing too).
Upvotes: 0
Reputation: 30285
Let's break it down into steps:
sw_addr
is a variable. The value of the variable is X.*sw_addr
means "the value at address X", meaning the value that we want to read into "switches".sw_addr
is of type void *
, we can't write switches = *sw_addr;
since the compiler doesn't know the size of the data that you want to read. Maybe you're trying to read only one byte, maybe two bytes, maybe four?(uint32_t *)sw_addr
tells the compiler to look at sw_addr
as if it were a pointer to a uint32_t
, meaning a pointer to an unsigned 32 bit value. *((uint32_t *)sw_addr);
(i've added another pair of brackets for clarity, but it doesn't matter) means the value pointed by our (uint32_t *)sw_addr
pointer i.e. the 4 byte unsigned value at address X.switches=*(uint32_t *)sw_addr;
and it's clear that we intend to read 4 bytes from address X into switches
.Alternatively, we could have written the following:
uint32_t *sw_addr;
int switches;
switches=*sw_addr;
Upvotes: 0
Reputation: 5557
sw_addr is a void
pointer. void
pointers cannot be dereferenced, because void is the no-type type, i.e. there is no such thing as void a;
as variable declaration. Therefore the pointer is cast to a uint32_t*
, before it is dereferenced. The value at the address of sw_addr is now interpreted as an `uint32_t, when it is dereferenced.
Edit: I should mention that the specific operation in your code might not be safe, because you are assigning the result to an int (which is signed, whereas the u in uint32_t
stands for unsigned). An int
may not be able to represent the number stored in a uint32_t
, first because unsigned int
s can store larger numbers, but possibly also because an int
is not guaranteed to be 32 bits large.
Upvotes: 2