Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is volatile needed when variable is only read during interrupt

The C standard states that the volatile keyword should be used in the definition of a variable when there's a chance that the variable's value could change outside the normal flow of execution of the program.

If a global variable is changed (written) during normal execution flow and only read outside this normal flow (in an interrupt). Does this variable need to be volatile ? And why ?

like image 830
Julien Avatar asked Mar 21 '19 10:03

Julien


People also ask

When should volatile be used?

When To Use Volatile in C/C++ A variable should be declared volatile whenever its value could change unexpectedly. In practice, only three types of variables could change: Memory-mapped peripheral registers.

Is volatile necessary?

Conclusion. The volatile field is needed to make sure that multiple threads always see the newest value, even when the cache system or compiler optimizations are at work. Reading from a volatile variable always returns the latest written value from this variable.

What is the purpose of a volatile variable?

Volatile keyword is used to modify the value of a variable by different threads. It is also used to make classes thread safe. It means that multiple threads can use a method and instance of the classes at the same time without any problem. The volatile keyword can be used either with primitive type or objects.

Why do we need volatile declaration for variable shared between the main and ISR?

Variables shared between ISR functions and normal functions should be declared volatile . This tells the compiler that such variables might change at any time, and thus the compiler must reload the variable whenever you reference it, rather than relying upon a copy it might have in a processor register.


1 Answers

If a global variable is changed (written) during normal execution flow and only read outside this normal flow (in an interrupt). Does this variable need to be volatile?

Yes absolutely.

And why?

To ensure proper execution of the interrupt handler (rather than the normal flow).


Let me elaborate.

Imagine you have a variable like this:

int x;

You are modifying this variable in the normal flow of the program as this:

void modify(int *x){...some code here...}

And in the interrupt service routine, you are reading the variable.

Remember that an interrupt can occur asynchronously(at any time). Also remember that the compiler will first convert your code into a series of machine instructions which could look something like this:

load val from mem to register
perform modification operations
store value from registers to memory
perform other operations where the variable is used

Now, the compiler may optimise this program to reduce the number of memory read-writes as such:

load value
perform modifications
use value
...
modify register content
...
use
...
keep using value from the registers without ever storing in the memory.

In such a case, if an interrupt occurs, (note that the interrupt context is usually different from the normal context and thus has different set of registers in a lot of architectures (say arm...)), it will attempt to read the value of the variable from the memory. But the contents of the memory have never been changed because of compiler optimisation.

So, the ISR could read an old value (worse still-we can't definitely say how old a value) which would result in unintended behaviour.

So, the variable should be declared as volatile to prevent the compiler from meddling with the program.

like image 119
Parth K Avatar answered Oct 10 '22 09:10

Parth K