Volatile
The formal definition of volatile is that it is a keyword used to tell the compiler to not perform any optimization to a variable, or to make any assumptions about the data. More English-y, a volatile variable is one that can change unexpectedly.
Modern C compilers perform a lot of optimization to make the binary smaller and more efficient, a very important trait for a resource-constrained system such as a microcontroller.
To understand why volatile is important, consider the following code snippet:
//Before main setup uint8_t my_love_for_cabbages = 255; int main() { while(true) { printf("Sahil likes cabbages this amount: %d\n", my_love_for_cabbages); } } ISR gpio_interrupt() //Interrupt for a GPIO { my_love_for_cabbages -= 1; }
As embedded systems programmers, we understand that an interrupt [see more here, Interrupts ] can occur at any time. However, to a compiler, the function
gpio_interrupt
does not appear to get called. As a result, the compiler says oh, look,my_love_for_cabbages
will never get updated since the functiongpio_interrupt
does not get called, why bother wasting the extra byte storing it in memory? Let’s just assume it stays at 255 and call it a day.You run this code, and the output variable is stuck at 255, since the compiler has optimized it out, since it has made the assumption that the data will not change.
Alternatively, you run this code, and the number does not go down by one but instead jumps randomly when you press the button.
In the above example, adding the word volatile tells the compiler the following 2 things:
my_love_for_cabbages
may update unexpectedly, i.e. in this case a GPIO interrupt that we do not know when will occur, so it should always take a fresh copy of the variable.my_love_for_cabbages
should not be optimized out by the code.
It is important to be aware of the effects of volatile in your code outside of interactions with hardware. Consider the following example:
//Taken from the 'C' test, linked in bibliography int square(volatile int *ptr) { return *ptr * *ptr; }
ptr is a pointer to a volatile integer, meaning its variable can change unexpectedly. Recall one of the effects of volatile - it will always take a fresh copy of the variable, meaning in line 5, it is possible to not multiply by the square since a fresh copy of ptr will be taken every time it is mentioned in the code. Thus, you may not get the square of the number in ptr.