Dunfield Development Services Inc.
Customer Support -- Application Note #0013
MICRO-C
Accessing "volatile" locations and devices

Applies to: [Micro-C Compiler
]
Last updated: Sunday May 04, 2003
.
Application Note Index
[ Back ] [ Next ]

PROCEDURE
The Micro-C optimizer performs an optimization called "Redundant Load Suppression" which may cause the compiler to incorrectly access memory
locations which are considered "volitile".
The term "volitile" is used to refer to locations which may not read the same value as was last written there. An example of this would be an I/O
port, where some of the bits are used for OUTPUT, and some bits are used for INPUT. When reading the port, the input bits will always reflect the
physical state of the corresponding digital input lines, and NOT the value last written to those bits by the processor.
Micro-C's "Redundant Load Suppression" optimization is intended to reduce unnecessary code produced when a variable is re-used immediately after it
is written. Examples are:
b = a;
c = b;
In this case, the compiler generates code which looks like:
LOAD a
STORE b
LOAD b
STORE c
The optimizer recognizes that the 'LOAD b' immediately following the 'STORE b' is unnecessary, and removes it, leaving a sequence which looks
like:
LOAD a
STORE b
STORE c
Another perhaps more common example, in which similar code would be generated is:
a = function();
if(a & 0x10) { ... }
In this case, the compiler generates code which looks like:
CALL function
STORE a
LOAD a
AND 0x10
JUMP_IF_ZERO ...
Again, the optimizer recognizes that the 'LOAD a' immediately following the 'STORE a' is unnecessary, and removes it.
For most cases involving RAM, or I/O ports which are output only, this would be correct, however if A is a port used for output AND input, the
intent of the programmer might be to write the output bits with the return value from 'function()', and then immediately test the 0x10 input bit. In
this case, the optimized code would fail, as it will test the 0x10 bit in the return value from 'function()', NOT the value read from the input port!
Some compilers use a "volatile" keyword to identify locations which should not be write/read optimized however Micro-C does not have this capability.
it is however quite easy to achieve the same functionality.
The cases where the Micro-C optimizer will perform Redundant Load Suppression are very specific, in particular, the location must be written,
and then IMMEDIATELY read. If any other operation occurs in between the write and the read, the optimization will not occur.
You can also take advantage of the fact that the optimizer considers a blank line or comment to be equivalent to "any other operation", and
therefore will not perform the optimization if a blank line or comment separates the write from the read. You will find that this optimization
does not get performed when the -C option is used to insert the C source code as comments. This is because the comments inserted by the compiler
between the write and the read prevent the optimizer from recognizing the sequence.
You can defeat specific Redundant Load Suppression optimizations by adding a asm""; directive to your code in order to force a blank line between the
write and the read operation:
a = function();
asm ""; /* Defeat RLS to insure volitile location re-read after store */
if(a & 0x10) { ... }
This inserts a blank line in the output code between the write to 'a', and the read from it, defeating the optimization.
You should keep this in mind and insert the asm""; whenever you are writing to an IO port and them immediately reading from it, and expecting to read
the actual hardware value. If you like, you can hide this in a #define:
#define VOLITILE asm""
a = function();
VOLITILE; /* Insure volitile location re-read after store */
if(a & 0x10) { ... }
Note that this "Redundant Load Suppression" problem occurs only on I/O locations which are mapped as memory devices, and read/written in two
consecutive C statements as simple variables. This problem will NOT occur on I/O devices which are accessed by peek/poke/in/out functions. |
|