A SERVICE OF

logo

CAVR-4
132
Writing efficient code
AVR® IAR C/C++ Compiler
Reference Guide
INTEGER TYPES AND BIT NEGATION
There are situations when the rules for integer types and their conversion lead to
possibly confusing behavior. Things to look out for are assignments or conditionals (test
expressions) involving types with different size and logical operations, especially bit
negation. Here, types also include types of constants.
In some cases there may be warnings (for example, constant conditional or pointless
comparison), in others just a different result than what is expected. Under certain
circumstances the compiler may warn only at higher optimizations, for example, if the
compiler relies on optimizations to identify some instances of constant conditionals. In
the following example an 8-bit character, a 16-bit integer, and two’s complement is
assumed:
void f1(unsigned char c1)
{
if (c1 == ~0x80)
;
}
Here, the test is always false. On the right hand side, 0x80 is 0x0080, and ~0x0080
becomes
0xFF7F. On the left hand side, c1 is an 8-bit unsigned character, and, thus,
cannot be larger than 255. It also cannot be negative, thus the integral promoted value
can never have the top 8 bits set.
PROTECTING SIMULTANEOUSLY ACCESSED VARIABLES
Variables that are accessed from multiple threads, for example from main or an
interrupt, must be properly marked and have adequate protection, the only exception to
this is a variable that is always read-only.
To mark a variable properly, use the
volatile keyword. This informs the compiler,
among other things, that the variable can be changed from other threads. The compiler
will then avoid optimizing on the variable (for example, keeping track of the variable in
registers), will not delay writes to it, and be careful accessing the variable only the
number of times given in the source code.
A sequence that accesses a volatile declared variable must also not be interrupted. This
can be achieved using the
__monitor keyword in interruptible code. This must be done
for both write and read sequences, otherwise you might end up reading a partially
updated variable. This is true for all variables of all sizes. Accessing a small-sized
variable can be an atomic operation, but this is not guaranteed and you should not rely
on it unless you continuously study the compiler output. It is safer to ensure that the
sequence is an atomic operation using the
__monitor keyword.