Difference between revisions of "Volatile Variable"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Created page with "This famous '''volatile''' variable article... Reading this article might just find you a job because C/C++ interviews tend to have this very common question on the list! Th...")
 
Line 16: Line 16:
  
 
Assembly code without volatile:
 
Assembly code without volatile:
<syntaxhighlight lang="assembly">
+
<syntaxhighlight lang="asm">
 
LOAD R0, &UART_STATUS
 
LOAD R0, &UART_STATUS
 
LOOP:  
 
LOOP:  
Line 24: Line 24:
  
 
Assembly code *with* volatile:
 
Assembly code *with* volatile:
<syntaxhighlight lang="assembly">
+
<syntaxhighlight lang="asm">
 
LOOP:  
 
LOOP:  
 
     LOAD R0, &UART_STATUS
 
     LOAD R0, &UART_STATUS

Revision as of 16:55, 18 September 2012

This famous volatile variable article... Reading this article might just find you a job because C/C++ interviews tend to have this very common question on the list!

The textbook definition of a volatile variable is: "Any variable that is subject to change externally should be declared volatile".

This often doesn't click in people's mind on what the volatile keyword actually does. It has to do with the way CPUs work and the way compilers optimize your programs. Let's assume that you are compiling in GCC with optimizations turned on and we've got a following loop:

// Assume you have a CPU register called UART_STATUS
// and you expect bit 0 to set sometime in near future
while(UART_STATUS & (1 << 0) == 0) {
 ; // Keep waiting
}

If UART_STATUS variable is not volatile, you've got a potential infinite loop even if the bit sets. This is a GCC optimization technique that has gotten you in trouble.

Assembly code without volatile:

LOAD R0, &UART_STATUS
LOOP: 
    CHECK R0, BIT0
    JUMP LOOP IF R0

Assembly code *with* volatile:

LOOP: 
    LOAD R0, &UART_STATUS
    CHECK R0, BIT0
    JUMP LOOP IF R0


Compiler Optimization

The compiler basically optimizes the loop taking for granted that the memory variable UART_STATUS is not changing INSIDE the loop, therefore, there is no need for a LOAD from memory instructions inside the loop, thus enhancing the loop performance. Using volatile keyword in this case tells the compiler that the variable is subject to change externally (outside of the context of the loop), therefore it should reload the memory whenever it is referenced.