The variable modified by volatile indicates that this variable may be unexpectedly changed. For programmers, this keyword is quite common in microcontroller programming.
Volatile means changeable and unstable. In fact, many people may have never seen this keyword and are unaware of its existence. There are also many who know of its existence but have never used it; I feel like it is a case of “a girl in the Yang family has grown up, raised in a deep boudoir, unknown to anyone.”
So what does the volatile keyword actually mean, and how is it used?
1. Volatile is actually a type modifier, similar to const. A variable modified by it indicates that it can be changed by factors unknown to certain compilers, such as the operating system, hardware, or other threads. When encountering a variable declared with this keyword, the compiler will not optimize the code that accesses this variable, thus providing stable access to special addresses.
① Let’s take an example:
int i=10;
int j=i; // ① statement
int k=i; // ② statement
At this point, the compiler optimizes the code because in statements ① and ②, i is not used as a left value (it is not assigned). The compiler believes that the value of i has not changed, so after taking the value of i from memory and assigning it to j, this value is not discarded but is used again to assign to k in statement ②. The compiler will not generate assembly code to retrieve the value of i from memory again (it will not compile the assembly instructions that load from memory, such as the ARM LDM instruction), thus improving efficiency. But note that it must be confirmed that i has not been used as a left value between statements ① and ②.
② Now let’s look at another example:
volatile int i=10;
int j=i; // ③ statement
int k = i; // ④ statement
The volatile keyword tells the compiler that i may change at any time. Therefore, every time it is used, the value of i must be retrieved from memory, and the assembly code generated by the compiler will read data from the address of i to place in k.
It can be seen that if i is a register variable representing port data or shared data between multiple threads, it can easily lead to errors. Thus, volatile can ensure stable access to special addresses.
2. We know that in technical jobs related to electronics, there is usually a written test during interviews, such as in microcontroller software, where questions will generally assess the knowledge of this keyword. This highlights the importance of this keyword in microcontroller programming. Common questions may ask for the definition of this keyword, which means you need to know its concept, and then provide examples of how this keyword is used. This can effectively assess everyone’s understanding of this keyword.
Generally, we know:
① Hardware registers of parallel devices (like status registers)
② Non-automatic variables accessed in an interrupt service routine
③ Variables shared by several tasks in multi-threaded applications
When we can answer these, we can basically conclude that you understand this keyword. If you work in embedded systems, programmers often interact with hardware, interrupts, RTOS, etc., so this keyword must be understood.
3. Let’s extend this a bit: a parameter can be both const and volatile. For example, a read-only status register is const, meaning the program must not attempt to modify it, and volatile represents a status register that may be unexpectedly changed.
4. Can pointers use the volatile keyword? Yes, they can.
We only need to understand this; it is not used frequently but must be known. For example, when an interrupt service routine modifies a pointer pointing to a buffer. The modification is similar to const; const has the concept of constant pointers and pointer constants, and volatile can also be thought of in this way, for example, modifying the object or data pointed to by a pointer as const or volatile.
For example:
volatile char *p1;
For example, the value of the pointer itself—a variable representing an address—is const or volatile.
For example:
char* volatile p1;
This keyword is not only present in C; other languages like C++ and Java also have it. In most other languages, it is due to errors arising from the compiler optimizing the use of shared variables in multi-threading. For example, if the compiler loads a variable from memory into a CPU register, then two threads may use one variable from memory and the other from the register, leading to erroneous program execution. Using volatile to modify the variable tells the compiler that every time this variable is manipulated, it must actually retrieve it from memory, not use the value already present in the register.
Do you now have a clearer idea of how to modify variables with volatile and which variables need this keyword?
Previous reviews:
● If you are feeling confused, check out this article!
● Stop saying your microcontroller RAM is insufficient; check this out…
● What is SysTick in STM32? How to use it?
END

