Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Need more clarification in Volatile keyword

Status
Not open for further replies.

bhadmanathan

Junior Member level 1
Junior Member level 1
Joined
May 7, 2016
Messages
18
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
187
Hi ,

Still i dont understand volatile keyword in c.I read that
A variable should be declared volatile whenever its value could change unexpectedly.
Ex: Memory-mapped peripheral registers

Embedded systems contain real hardware, usually with sophisticated peripherals. These peripherals contain registers whose values may change asynchronously to the program flow. As a very simple example, consider an 8-bit status register at address 0x1234. It is required that you poll the status register until it becomes non-zero. The nave and incorrect implementation is as follows:

Code:
UINT1 * ptr = (UINT1 *) 0x1234;

// Wait for register to become non-zero.
while (*ptr == 0);
// Do something else.

This will almost certainly fail as soon as you turn the optimizer on, since the compiler will generate assembly language that looks something like this:

Code:
mov    ptr, #0x1234     
mov    a, @ptr loop     
bz    loop

The rationale of the optimizer is quite simple: having already read the variable's value into the accumulator (on the second line), there is no need to reread it, since the value will always be the same. Thus, in the third line, we end up with an infinite loop. To force the compiler to do what we want, we modify the declaration to:

Code:
UINT1 volatile * ptr =
    (UINT1 volatile *) 0x1234;

The assembly language now looks like this:

Code:
mov     ptr, #0x1234
loop    mov    a, @ptr        
bz    loop

The desired behavior is achieved.




But,i done the following code ..

Timer0 in pic16f877a is memory mapped at 0x01. I created a non volatile pointer variable to point that address.

Code:
void main()
{
	
	unsigned char *p=0x01;
	Lcd8_Init();

	OPTION=0x07;//turn on timer0

	while(1)
	{
		Lcd8_Decimal3(0x80,*p);
		Lcd8_Display("BEFORE WHILE");
		while(*p<254);
		Lcd8_Display("AFTER  WHILE");
                while(1);
	}
}

I expected that LCD will display "BEFORE WHILE" and while(*p<254); become infinite loop. But the above code is working fine without volatile and it displays "AFTER WHILE".

What i have done wrong??

Thanks in advance
 
Last edited by a moderator:

Nothing!

Volatile is a hint to the compiler that a value might change unexpectedly due to some other influence. It tells the compiler that if it optimizes the code (something most complilers can do) it shouldn't assume that a value stays the same if it gets used again. If the compiler didn't try to optimise a particular part of your code it would make no difference to operation. Example:

A = 1;
B = A + 1;
C = A + 2;

you would assume the value of B would be 2 and C would be 3. An optimising compiler might see this as "I know A is 1, add 1 to make B = 2, add another 1 to make C = 3".

Now consider what might happen if 'A' was a value in an input port and it changed during the calculations. The correct response would be to add 1 to the value currently in the port but the optimizer might say "add it to the value of 'A' I already know". The same might happen if 'A' was changed by an interrupt routine during the execution of the three lines. When you declare it 'volatile' you tell the compiler not to assume the value has not changed and check it again.

Normally you would only declare a variable volatile if it was used both inside and outside an interrupt routine or in some special cases where the variable is a memory mapped peripheral. In other words, situations where it might change independantly of the main program flow.

Brian.
 

I agree that your timer example
Code:
unsigned char *p=0x01;
...
while(*p<254);
is a case where optimization could cause code failure so that the volatile keyword is basically appropriate.

It's however questionable if the 8-Bit PIC compiler uses this degree of optimization. If it does, it might have an built-in rule to treat SFR implicitely as volatile. There's nothing against using volatile for all kind of hardware registers that can change their value without being explicitly written. But it might be unnecessary under circumstances.
 

I can't find anything in the MPLABX or 'XC' compilers that specifically states internal registers are treated as volatile but it would seem to be sensible to do so, at least in some cases. The first code in the original post isn't for PIC though and the second code might be for a different PIC compiler.

Brian.
 

Hello Sir,
I accept that every SFR's are implicitely Volatile.
Actually i opened <pic.h> header file, there they have included <pic168xa.h> i opened that too.There i saw the following..

volatile unsigned char INDF @ 0x00;
volatile unsigned char TMR0 @ 0x01;
volatile unsigned char PCL @ 0x02;
volatile unsigned char STATUS @ 0x03;
volatile unsigned char FSR @ 0x04;
volatile unsigned char PORTA @ 0x05;

clearly every SFR's are Volatile by default, but i removed volatile keyword and run the code, it was also working fine..

Here only i got doubt.

What is wrong in the above..

Thanks in advance
 

See, the code may still work if you do not use the volatile keyword. But, it may break anytime (or maybe not). I will elaborate

Say, e.g you have a global integer being used in your main routine in C program. Its value is changed in the main routine (not in any other functions to keep example simple). Now you know that the compiler will "optimize" the low level code generated after compilation. Thus may exclude certain parts of the code we wrote because they are considered to be "redundant" since the value of this varialble is not likely to change between some two lines of your program the resulting code is optimized that way.

Now assume that the value of this integer may change in an ISR. Remember, an ISR can run at ANYTIME and is completely unpredictable. It interrupts the normal program flow. Thus, it is possible but not important that the value of the integer changes such that when the optimized normal program resumes, it is in such part of the program that it expects that the integer has not changed (while it has) and the program behaves strangely or simply breaks.

If you use the term volatile, the compiler will not carry out these unecessary optimizations and your life will be much easier. Bugs caused by leaving out volatile may be hard to reproduce and track down. As you can see, it really is down to this being need of the compiler.
 

... which basically repeats what I already said in an earlier post.

Nothing is wrong in the code.

If the compiler (you haven't said which one you use) tries to optimize your code it MAY produce wrong results if some other part of the program, an ISR for example, or some hardware influence changes the value held in the variable. Adding 'volatile' drops a hint to the compiler that it should not try to optimize instructions using that variable because it may change outside of program control. If the compiler didn't optimize it, the code and execution would be exactly the same. It is entirely down to the authors of the compiler as to whether their algorithms decide it can be optimized or not.

'volatile' is a defensive prefix used by the compiler, it doesn't necessarily make any change in executable code and whether you use it or not is up to you. Good programming practice says use it where necessary but not everywhere as that would negate all optimizations. Typically, you would use it where the same variable was used both inside and outside an ISR and the ISR code could modify it's value.

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top