![]() |
Volatile and Registers
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? |
Re: Volatile and Registers
Mike Halloran wrote:
> 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. -- Eric Sosman esosman@ieee-dot-org.invalid |
Re: Volatile and Registers
Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
> Mike Halloran wrote: > > 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) > > 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 |
| All times are GMT. The time now is 07:21 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.