batata004:
I really appreciate everything you said but I still didnt understand the "veredict". Do I need to declare a variable as volatile if its value is not changed inside the interrupt or ISR routine? My variable is not a constant, it may be changed inside the "loop" routine but inside interrupt or ISR it will surelly not be changed, should I declare it as volatile?
Your description is incomplete.
You haven't said what each entity is doing with the variable.
(looking at it or modifying it etc...)
It is best to understand what volatile means so you can determine how and when to use it rather than try to get an answer for a specific case.
volatile is used when you have more than one entity (or thread) that is looking at or using the same variable.
It ensures that each thread is flushing the variable to memory so the other thread can have access to the latest update. This is very important when one thread can interrupt/pre-empt another thread which is what happens when an ISR runs.
If you only have 1 thread, either foreground or ISR, that accessing the variable, there is no contention and so volatile is not needed.
You will also need to understand the concept of atomicity as this is very important to volatile variables since the AVR is an 8 bit RISC processor. This means if you are doing something like incrementing a 16 bit variable the value may be seen as "corrupt" since the increment operation is an interrupt able operation.
volatile and atomicity are distinctly different but go hand and hand in that if you are using volatile variables you can easily have an atomicity issue, particularly on something like the AVR when using larger than 8 bit variables.
You can think of volatile as forbidding variable caching. The compiler is smart and will try to leave a variable in a register as long as possible to make the code more efficient and faster. If you make the variable volatile it disables this and the compiler is told to access and update the variable from its real memory location each and every time the variable is accessed or modified.
This is critical if say foreground code is in a loop and looking at a global variable that an ISR is setting.
If the variable was not declared volatile, the foreground code might not see the actual memory update since it would be looked at a "cached" copy of the variable instead of the actual variable in the memory location.
Same is true on the reverse, in that if you have foreground code in a loop that has modified a global variable that the ISR is looking at. If the variable was not declared volatile, then ISR might not see the updated global variable since the foreground loop may not have written it back to memory yet - and might not ever write it to memory.
But again, if you only have 1 thread that looking at and using the variable, regardless if whether that thread is an ISR, volatile is not needed.
atomicity is something else and issues related to it can be subtle and difficult to track down.
Lack of atomicity can cause apparent variable corruption even when volatile is used.
While volatile tells the compiler not to cache the variable, it does not ensure that the value of a variable is fetched or updated atomically.
Issues with atomicity can happen whenever an update to a variable can be interrupted.
This is true for 16 bit variables on an 8 bit processor like the AVR.
For example if you have a volatile variable that is an int (which is 16 bits on the AVR)
an operation like ++, --, or bit operations |= &= ^= ~= and others can be interrupted during the update for each byte.
If you need to ensure atomicity, for larger than 8 bit values, then you have to ensure that the update operation is not interruptible.
To protect a foreground update from an ISR you have to mask interrupts.
Note that there can be atomicity issues even with 8 bit values on the AVR.
An operation like
foo |= bitmask;
Is atomic if bitmask a constant, but is not atomic if bitmask is not a constant.
--- bill