Volatile and Registers

M

Mike Halloran

Normally, when I write software to access a register, I will do
something like this:
*((volatile u32*) 0x00000022) = 5; (with some wrappers to make it
cleaner)

however, I noticed that in a recent codebase that my company aquired,
volatile
is not used:
*((u32*) 0x00000022) = 5;

Is this a proper way of coding? I was under the understanding that if
volatile is not used, the code could be optimized out. Is this
correct? What does
everyone else do?
 
E

Eric Sosman

Mike said:
Normally, when I write software to access a register, I will do
something like this:
*((volatile u32*) 0x00000022) = 5; (with some wrappers to make it
cleaner)

however, I noticed that in a recent codebase that my company aquired,
volatile
is not used:
*((u32*) 0x00000022) = 5;

Is this a proper way of coding? I was under the understanding that if
volatile is not used, the code could be optimized out. Is this
correct? What does
everyone else do?

First, I hope you realize that converting integers to
and from pointers is inherently "unclean," and relies on
characteristics of the particular system you happen to be
using. It's a common technique for getting at things like
hardware registers, but it's not a portable technique.

Now, as to `volatile'. Nothing in the "register-ness"
of the target location requires `volatile' in and of itself,
but in some circumstances you may need it. For example, you
might send output to some device by writing successive bytes
to an I/O register:

u32 *ioreg = (u32*)0x00000022;
*ioreg = 'H';
*ioreg = 'e';
*ioreg = 'l';
*ioreg = 'l';
*ioreg = 'o';

This may well fail if the compiler observes that the results
of the first four assignments are unused and so eliminates
them, leaving you with only the last. Adding `volatile' to
the pointer declaration

volatile u32 *ioreg = (u32*)0x00000022;

tells the compiler that each access to `*ioreg' counts as a
necessary side-effect, and obliges it to retain all five
assignments.

It also requires the compiler to generate the side-effects
in the proper order. Let's imagine an I/O device with both a
"command register" and a "data register:"

u32 *cmnd = (u32*)0x1000;
u32 *data = (u32*)0x1004;
*data = '?';
*cmnd = CMD_STROBE;

Alas, this might not work: The compiler could decide to swap
the order of the assignments or maybe to combine them both into
one 64-bit store. By declaring both pointers `volatile' you
tell the compiler that each access is a side-effect, and
since the compiler is not allowed to rearrange the order of
side-effects the two assignments will be performed in the
order you intended.

My examples have involved assigning to the volatile
object, but reading from it may also be a side-effect. For
example, imagine a hardware timer:

hires_t *timer = (hires_t*)0x12345678;
hires_t t0, t1;
t0 = *timer;
lengthy_computation();
t1 = *timer;
printf ("Elapsed time: %f microseconds\n",
(double)(t1 - t0) / (HIRES_TICKS_PER_SEC * 1e6));

If the compiler deduces that lengthy_computation() does not
store to `*timer', it may fetch the value of `*timer' just
once, making `t0' and `t1' equal no matter how long the
computation runs. The desired side-effect of reading the
updated value of `*timer' has been lost. Again, the cure is
to use `volatile' to tell the compiler that the side-effect
exists and is required, and to force it to fetch twice.

Summary: Whether `volatile' is needed depends not on the
nature of the location being accessed, but on what you plan
to do with it.
 
R

Richard Bos

Eric Sosman said:
First, I hope you realize that converting integers to
and from pointers is inherently "unclean," and relies on
characteristics of the particular system you happen to be
using. It's a common technique for getting at things like
hardware registers, but it's not a portable technique.

Actually, the technique itself is portable. The numbers are not. I would
not expect any given system to let you write to any given address, but
if some system does allow you to write directly to some addresses, this
is precisely the technique I would expect to be able to use.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top