• Pouya Neshagar

Use of 'Volatile' keyword in Embedded C

Updated: Jan 22, 2018

Imagine that you are in an interview for a job and. The interviewer gives you the following code, and asks you to find the problem [1]:


void IO_WaitForRegChange(unsigned int* reg, unsigned int bitmask)

{

unsigned int orig = *reg & bitmask;

while ( orig == (*reg & bitmask) ) {/* do noting */ ;}

}


You can say that “there is no comment header for documentations” or point that “why we should wait for a register change and do nothing without a proper error handling and timeout”. There are all true, but still you are missing the important part. If you fail to mention the critical thing, the interviewee might add that the function never returns despite the register changes monitored by oscilloscope and that the code compiles with optimizations ON.


So, what is the problem?

The register had changed, but why our code didn’t work?

why optimization was important to mention by interviewee?

Does Optimization OFF or ON makes a difference here?


We will get back to the question again, but first let’s see what is a ‘Volatile’ in C and why it’s important in Embedded C.


Volatile

In C, Volatile, is a qualifier to a variable. By making a variable, a volatile variable, we are telling the compiler that:

“value of this variable, might change by some external sources that you may not see nearby. So please kindly do not do any optimization on it and go and read it again each time you need its value. “

and that is really useful and important in Embedded C, since we are working with hardware, registers, and interrupts on daily basis.

  • We have Interrupt Service Routine (ISR) that we might change the value of a variable if some interrupt has occurred. Timer interrupts, for instance, are something that widely used.

  • It might me the case of a memory-map registers that the value might change by some hardware or some I/O port.

  • Maybe you have multi-threaded application and the value of your global variable might change in another thread.

In all the above important cases, change to the value of a certain variable may not be done by nearby code but, by some external forces. So, it’s important to declare them as Volatile variable and tell the compiler about the situation.


The syntax of using Volatile:

To declare a volatile variable, you just need to add the qualifier to the declaration.

volatile int reg;

int volatile reg;


As you may expect in Embedded C, pointer to a volatile variable are common:

volatile uint8_t * pReg;

uint8_t volatile * pReg;


"volatile pointer to a variable" and “volatile pointer to a volatile variable” are also possible and exist but rarely is the case that you might use them.

int * volatile p; /* volatile pointer to an integer*/

int volatile * volatile p;

/*volatile pointer to a volatile integer*/



Le'ts take a good look at the interview question again. We are trying to read a register and we are waiting for its value to change. But since Optimization is On, and we didn’t tell the compiler that the reg’s value might change somewhere else that you don’t see around, the compiler will cut some corner to save some space or do something to increase the speed and basically will not go and read the register's value each time in our while loop.

Why? because it didn’t find the reason to, because we didn’t tell it to.


Therefore, to answer the interview question, we are missing ‘volatile’ keyboard in variable declaration for ‘reg’.


But, what if, we set the Optimization Off? What would happen differently?


Without the Optimization, the interview’s code should work fine even without Volatile keyword. Because, the compiler will not try to optimize for speed or for space and basically will go and read the value from memory each time. But, even if the Optimization is OFF and your are making it OFF by intention, it’s considered bad practice to miss the Volatile keyword for such variable. It adds readability to your code so that future you or somebody else knows what is going on by seeing a 'Volatile' variable. Also, it will save you a lot of time confusion if suddenly you decided to turn the Optimization ON later on.


So, make sure to use 'Volatile' keyword when is needed whether the Optimization is On or Off.

I also recommend watching these two short YouTube videos.

To know more about what is happening in background inside compiler, please see:

https://www.youtube.com/watch?v=W3pFxSBkeJ8


And to see the different between Optimization ON and OFF in practice, please watch this:

https://www.youtube.com/watch?v=ImHW6I0BoEs



Knowing the reasons and background behaviour of certian things would help you and saves you alot of time down the road in your Embedded careers. So, as always, I encourage you to ask WHY and look for background behaviors when you are trying to learn new concepts in Embedded C. Asking better questions, will help you find better answers.



References:

[1] White, E. (2011). Making Embedded Systems. O'REILLY, p.108.

-------------------------------------------------------------------------------------

If you find this article useful, share it so that your friends can also benefit. It would be pleasure to have you as a subscriber, so make sure to subscribe to the newsletter to stay on top my featured blog posts each month.

© 2020   |   Helsinki, Finland   |  Pouya (at) PouyaNeshagar.com   |        | Legal: Cookies

  • LinkedIn Social Icon