>"Eric Sosman" wrote:
>> The solution to your problem is to qualify the "CMOS" thing
as volatile, and use an ordinary comparison:
struct {
...
volatile unsigned char uc;
...
} *cmos = ...;
(Or, as I tend to prefer, make the structure type's elements
ordinary, non-"volatile"-qualified, but use a volatile qualifier
on the pointer itself:
struct whatever { ... unsigned char uc; ... };
volatile struct whatever *cmos = ...;
This allows one to copy the entire data structure into ordinary
RAM, then manipulate it there without defeating optimization.)
>>cmos->uc = uc;
if (cmos->uc == uc) ...
The compiler is not permitted to optimize away any of the accesses
to cmos->uc, because the volatile qualifier declares that those
accesses have side-effects ...
(Or rather, that they "may" have side effects, and the compiler
should assume the worst.)
>"Martin" <martin.o_brien @[no-spam]which.netwrites :
>Thanks for your comments. I don't think making the cmos variable
volatile is an option.
Why not? (Neither Eric Sosman's method nor mine generally requires
much in the way of code changes.)
>Why can't I make uc volatile?
You can; it just is silly, and may well not work. (In fact, it is
only likely to work if the code happens to work with no "volatile"
qualifiers anyway. That is, adding the volatile qualifier in the
wrong place is extremely unlikely to help.)
[I am going to make a name change below, so that "uc" unambiguously
refers to cmos->uc, and use "temp_v" for the local variable.]
> volatile unsigned char temp_v = (unsigned char) ui32;
cmos->uc = temp_v;
if ( cmos->uc != temp_v )
/* error writing to CMOS */
In article <87************ @bsb.me.uk>
Ben Bacarisse <be********@bsb .me.ukwrote:
>Making temp_v volatile won't work.
Well, it *might* work, all depending on details about the
compiler's internal workings.
>The compiler may assume that cmos->uc is set as per the assignment
(it need not access the object again).
Right -- for instance, it might generate code of the form:
ldw cmos_, a3 # so that register a3 = cmos
ldb -12(sp), d1 # so that register d1 = temp_v
stb d1, 48(a3) /* cmos->uc = temp_v; */
ldb -12(sp), d2 # so that register d2 = temp_v
cmp d1, d2 /* see if cmos->uc == temp_v */
...
Note that temp_v was loaded twice, in case it changed; but the
compiler could see that 48(a3), which refers to cmos->uc, was set
from register d1, and -- since it is "ordinary RAM" (even though
it is not!) it must not have changed, so there was no need to load
*that* again.
>I can't see a way round this other than making the object that is
actually volatile, volatile.
Indeed.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.