(... making the CMOS structure volatile) will only work
(as others here have pointed out) in the case where the item I am
writing and verifying in the cmos structure can be compared with a
simple ==. Where I write a structure such as a date/time (using
memcpy) I need to use memcmp to check that it wrote properly ...
Using memcmp() is rather likely to fail anyway, depending on
the target architecture.
Suppose memcmp() is a typical assembly-language "optimized" version,
that checks the alignment of its incoming pointers and the sizes
of the regions to compare. If the size is large enough (at least
4 or 8 bytes) and the addresses are properly aligned, it does, in
effect, the assembly equivalent of the following C code:
unsigned char *left, *right; /* then initialized from parameters */
size_t len; /* initialized from parameter */
if (properly_aligned) {
while (len >= sizeof(int) && *(int *)left == *(int *)right)
left += sizeof(int), right += sizeof(int), len -= sizeof(int);
}
while (len) {
if (*left != *right)
return *left < *right ? -1 : 1;
left++, right++, len--;
}
return 0;
Now, on a lot of hardware, *(unsigned char *)addr does a 1-byte
read on the bus, which is what is required to access an EEPROM
device; but *(int *)addr does a 4-byte read on the bus. If a 4-byte
read reaches the EEPROM ("CMOS") hardware, an incorrect value is
read from the device, or an exception ("bus error" or similar) is
delivered to the CPU.
Not all hardware works like this[%], and sometimes memcmp() really
can be used directly against "hardware memory", but exceptions
are common enough (in my experience anyway) to assume the worst,
and avoid memcmp() here.
[% Two particularly bizarre examples occur with 8-bit hardware
attached to "32-bit-only" CPUs. Here, "load byte" does a 32-bit
bus access, or there is no separate "load byte" instruction, so
the hardware designer takes one of two approaches. Either every
8-bit byte is placed on a 32-bit boundary, so that *(int *)addr is
0x000000NN or 0xNN000000 depending on endian-ness -- and sometimes
the 00s are FFs instead, or are duplicates of the NN byte; or,
instead, the 32-bit access is put on hold while the adapter does
four 8-bit accesses so as to "construct" the full 32 bit value,
which is then placed on the data bus. In this second case, it
really *can* be good idea to use 32-bit operations to access the
device -- typically to copy the entire ROM contents to RAM for
faster reference.]