If you experience problems with your code: - when reading and writing to memory mapped hardware
- getting stuck in loop, when polling hardware
- exhibiting strange behaviour in threaded programs
If these are particularly apparent at higher optimization levels (-O2 and -O3) but not at lower optimization levels it is likely that you may need to declare some of your variables as volatile. If a variable is declared as volatile the compiler can assume that the object may be changed out of its visibility. This means the compiler can not perform a number optimizations, including caching variables in local registers, to avoid memory accesses. If a variable is not declared as volatile the compiler can assume that the value has not changed and perform a number of optimizations on it. There are a number of different situations where you might wish to declare variables as volatile. These include: - Accessing memory mapped peripherals
- Variables shared between multiple threads
- Global variables accessed in interrupt routines
The following simple example demonstrates the effect on code generation when declaring a global variable as volatile. C code: /* volatile */ int buffer_full; void read_stream(void) { int count; while (!buffer_full) { count++; } } Code generation when buffer_full is not declared as volatile LDR r0,[pc,#12] ; Load address of "buffer_full" LDR r0,[r0,#0] ; Load "buffer_full" loop CMP r0,#0 ; Check "buffer_full" BEQ loop ; If not "buffer_full" branch to loop --> code stuck in loop! Code generation when buffer_full is declared as volatile LDR r1,[pc,#12] ; Load address of "buffer_full" loop LDR r0,[r1,#0] ; Load "buffer_full" CMP r0,#0 ; Check "buffer_full" BEQ loop ; If not "buffer_full" branch to loop Note that the count++ has been optimized away as it has no effect on the program.
|