When to declare variables as "Volatile"?

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
The_RB
Posts: 172
Joined: 18 Jan 2008 05:32
Location: Australia
Contact:

When to declare variables as "Volatile"?

#1 Post by The_RB » 27 Nov 2009 21:08

Hi, is there a general rule when it is required in MikroC or MikroC Pro to declare variables as "volatile"?

Is this only an issue when using some data structures, which the compiler uses indirect addressing?

I always thought if a variable was defined as a ram location (ie all global variables) the compiler will always reference the ram location so they are "volatile" by default?

In what situations with MikroC or MikroC Pro should I always declare vars as volatile?
Using; EasyPic4, EasyPIC6, BigPic4, MikroC. MPLab, MPASM.
C since 1991, PIC asm since 1998. Author of many freeware and open-source goodies; www.RomanBlack.com Designer of the www.TalkBotBrain.com talking PIC project.

The_RB
Posts: 172
Joined: 18 Jan 2008 05:32
Location: Australia
Contact:

#2 Post by The_RB » 01 Dec 2009 00:37

Has anyone got any answers for this?
Using; EasyPic4, EasyPIC6, BigPic4, MikroC. MPLab, MPASM.
C since 1991, PIC asm since 1998. Author of many freeware and open-source goodies; www.RomanBlack.com Designer of the www.TalkBotBrain.com talking PIC project.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#3 Post by janni » 01 Dec 2009 02:17

All variables are placed in RAM (not only globals), so the distinction with qualifier volatile means more than just type of memory.
I think that help explains it pretty well:
The qualifier volatile implies that a variable may change its value during runtime independently from the program. Use the volatile modifier to indicate that a variable can be changed by a background routine, an interrupt routine, or I/O port. Declaring an object to be volatile warns the compiler not to make assumptions concerning the value of an object while evaluating expressions in which it occurs because the value could be changed at any moment.

The_RB
Posts: 172
Joined: 18 Jan 2008 05:32
Location: Australia
Contact:

#4 Post by The_RB » 04 Dec 2009 05:24

Thanks for that, so since the ports and hardware registers must be volatile by default the only variables I need to declare as voltatile are ram variables I modify in an inerrupt?

The compiler seems to access those ram variables by just reading the ram location (when I check the assember output). So they seem to be volatile by default too.

I suppose what would be nice to know is when the compiler does NOT access the ram variable, like if there is a particular data structure, table, struct, etc that means the compiler won't access the ram but it will access a copy of the ram. If anyone knows the rules regarding that, please inform me.
Using; EasyPic4, EasyPIC6, BigPic4, MikroC. MPLab, MPASM.
C since 1991, PIC asm since 1998. Author of many freeware and open-source goodies; www.RomanBlack.com Designer of the www.TalkBotBrain.com talking PIC project.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#5 Post by janni » 04 Dec 2009 12:55

The_RB wrote:Thanks for that, so since the ports and hardware registers must be volatile by default the only variables I need to declare as voltatile are ram variables I modify in an inerrupt?
Mostly, yes. Declaring variable volatile switches off some optimisation - it may sometimes be used to manually optimise the code (though the optimiser gets more agressive with every version :twisted: :lol: ) or to be able to safely use the processor's indirect addressing mechanism.
The compiler seems to access those ram variables by just reading the ram location (when I check the assember output). So they seem to be volatile by default too.
There's no other way to access a variable, but to read/write it's RAM location :) . Problem arises, when value of such variable is stored in another, internal one and, for example, both are used in a block of code. This may lead to unpredictable results if an interrupt happens changing only the original variable.
I suppose what would be nice to know is when the compiler does NOT access the ram variable, like if there is a particular data structure, table, struct, etc that means the compiler won't access the ram but it will access a copy of the ram. If anyone knows the rules regarding that, please inform me.
There's no such mechanism, I'm afraid. One has to take care about it by oneself.

Mince-n-Tatties
Posts: 2780
Joined: 25 Dec 2008 15:22
Location: Scotland

#6 Post by Mince-n-Tatties » 04 Dec 2009 14:51

Hi RB,

for me this was always something that i used to control optimisation on systems which where perhaps not designed specifically as embedded.

imagine a variable which gets changed by external influence (input pin state changes PORT register value). ok, so now you have a loop which contains test logic on that variable while no other code exists in the loop which could alter the variable! with non-specific (or badly written) compilers the optimisation run would look at this and decide nothing can change this variable in this code loop so i will code reduce here BANG doesnt work in the embedded world where variables are hardware driven.

i once came across a good wiki example of this, try wiki search with C volatile variable or something along those lines. If i find it i will PM for your reading pleasure.

The_RB
Posts: 172
Joined: 18 Jan 2008 05:32
Location: Australia
Contact:

#7 Post by The_RB » 05 Dec 2009 03:23

Thanks people for the replies, I appreciate it! :)

Mince, I read the Wiki page you told me about, thanks too for that. It said pretty much what I already knew about use of volatile.

What I was after was any specific conditions that the MikroC/PRO compilers use that would help me decide when to declare volatile.

Now I'm just back to square one, ie code it up and look at the compiler output to see what it did... As always. :)

Code: Select all

Janni said;
...  There's no other way to access a variable, but to read/write it's RAM location  ....
I'm not sure that's true. I think in some compiler operations (some math functions etc) the compiler copies the variable to the stack and works on it there, than only saves it back to ram after the operation is complete. So the compiler is not working on the ram variable but instead works on the copy.

It would be nice to know at what times the compiler is going to work on a copy and the times when it will always work directly on the ram location.
Using; EasyPic4, EasyPIC6, BigPic4, MikroC. MPLab, MPASM.
C since 1991, PIC asm since 1998. Author of many freeware and open-source goodies; www.RomanBlack.com Designer of the www.TalkBotBrain.com talking PIC project.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#8 Post by janni » 05 Dec 2009 14:25

The_RB wrote:I'm not sure that's true.
Well, it is, but I understand now that you meant reading variable's value, wherever it was stored, i.e. by accessing the variable or it's copy.
I think in some compiler operations (some math functions etc) the compiler copies the variable to the stack and works on it there, than only saves it back to ram after the operation is complete.
Naturally, compiler does that to optimise code and that's where the volatile directve is sometimes needed. Looks like my explanation wasn't clear enough :( .
It would be nice to know at what times the compiler is going to work on a copy and the times when it will always work directly on the ram location.
I think that you're looking at it from wrong side. It's possible to analyse the optimisation methods used by the compiler and look thru code fragment after code fragment to decide if one of them will be used, but it's hardly practical (especially that new methods are going to be implemented soon). Much more practical is to use the volatile directive in all cases where the optimiser just could use variable's copy or it's value at compile time with undesired effect, i.e. for variables that are

- declared at some SFR address (most of them),
- changed by ISRs,
- modified by indirect addressing (using INDF or similar instructions in C).

Note, that declaring a global variable volatile will not help in 'bad conditioned' cases where it's modified in a function and both are used in the same expression, like

Code: Select all

char dummy(char bb)
{
  var8++;
  return bb--;
}

void main() {
   var8=var8+(3*dummy(5)+var8/2);
The result will differ from algebraically equivalent

Code: Select all

   var8=var8+(var8/2+3*dummy(5));
due to use of buffers (here, a copy of var8) at some stage of expression evaluation.

The_RB
Posts: 172
Joined: 18 Jan 2008 05:32
Location: Australia
Contact:

#9 Post by The_RB » 09 Dec 2009 15:27

Thank you for the specific examples Janni.
:)
Using; EasyPic4, EasyPIC6, BigPic4, MikroC. MPLab, MPASM.
C since 1991, PIC asm since 1998. Author of many freeware and open-source goodies; www.RomanBlack.com Designer of the www.TalkBotBrain.com talking PIC project.

Post Reply

Return to “mikroC PRO for PIC General”