I have been reading about accessing Memory Mapped Registers of peripheral devices and it seems you can do multiple ways. For example:
Method 1:
#define MyReg 0x30610000
volatile int *ptrMyReg;
ptrMyReg = (volatile int *) MyReg;
*ptrMyReg = 0x7FFFFFFF; /* Turn ON all bits */
Method 2:
#define MyReg 0x30610000
volatile unsigned char *ptrMyReg;
ptrMyReg = (volatile unsigned char *) MyReg;
*ptrMyReg = 0x7FFFFFFF; /* Turn ON all bits */
Question: Is there any specific reason as to why one would choose one over another?
Assume: Size of int on architecture is 4 bytes.
*ptrMyReg = 0x7FFFFFFF;
In the second case, *ptrMyReg
is of type unsigned char
so 0x7FFFFFFF
will be converted to unsigned char
(ie, value after conversion will be 0xFF
) before assignment and only one byte will be written. I don't think this what you want if you originally intended to write 4 bytes.
Well, the second example isn't valid code, since your typecast doesn't match. If you fix that to be:
ptrMyReg = (volatile unsigned char *)MyReg;
Then, yes, they're different. In the second case, that constant gets truncated, and you will write only 0xFF
to either the most- or least-significant byte of the word at 0x30610000
, depending on endianness. Regardless, it's the single byte at 0x30610000
that will be written to, and not others.
The CPU architecture may require that all accesses to perihperal registers are eg 32 bits wide. If so, doing byte access may cause CPU exception or silent erroneous execution. This is the case on many ARM SoCs.
In method 2, you aren't going to access the entire int
by dereferencing a pointer to char
(unless, of course, sizeof(int)
=1 on your platform).
Other than that, you should look at your hardware. It may behave differently when accessed using memory operands of different sizes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.