• AVR Freaks

Hot!Do we really need the volatile qualifier?

Author
DavidePizzolato
Junior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2010/11/25 11:55:54
  • Location: 0
  • Status: offline
2011/02/03 07:14:03 (permalink)
0

Do we really need the volatile qualifier?

In the forum, a common answer to solve problems with interrupts is something like “declare the variable as volatile”.
I have fully functional softwares with many shared variables and many interrupts, without any volatile variable. I wonder if sooner or later I will need a volatile variable too.
 
It seems that a problem with non-volatile variables comes if I write a conditional loop in this way:
while (nStatus)
{

}
That can result in an endless loop if nStatus is set by a different ISR. But using a simple while statement inside an ISR is also quite dangerous, because we have to provide a guaranteed return path within the interrupt timing. For this reason I avoid the "while" loops with shared variables, and probably this is the reason why volatile variables are no necessary.
 
My question is if there are any other well known cases to take care of, when using shared variables.
#1

19 Replies Related Threads

    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 08:45:10 (permalink)
    0
    Hmm, in my opinion "volatile is needed anytime a IRQ-modifiable variable is used in the main loop".
    So, not just a While(), but also a IF or other kind of assignment: the point is that you never know when the Optimizer (real "culprit" of this all) will decide that your variable is never changed in the Main loop, and hence turn it into a fixed value (or register).

    GENOVA :D :D ! GODO
    #2
    DavidePizzolato
    Junior Member
    • Total Posts : 95
    • Reward points : 0
    • Joined: 2010/11/25 11:55:54
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 09:27:46 (permalink)
    0
    that is a nice rule Dario. I try to shrink a bit its scope, with a negative version:
    "never use non-volatile variables directly in the main loop".
    If the rule is valid, we can write:
    void main(void)
    {
      HardwareInitialization();
      VariablesInitialization();
      while(1)
      {
        MainHandler();
      }
    }

    And dismiss the volatile qualifier
    #3
    Antipodean
    Super Member
    • Total Posts : 1724
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 09:43:42 (permalink)
    0
    DavidePizzolato

    that is a nice rule Dario. I try to shrink a bit its scope, with a negative version:
    "never use non-volatile variables directly in the main loop".


    I think you need to get a proper handle on what the 'volatile' operator tells the compiler. It can be necessary to use 'volatile' even when the variable is not associated with an interrupt.
     
    For example have a look in the files that come with the compiler, and see that all the I/O ports are specified as 'volatile'.
     
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #4
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11248
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 11:59:32 (permalink)
    +5 (3)
    DavidePizzolato

    "never use non-volatile variables directly in the main loop". 
    If the rule is valid,

    That is definitely not valid.

    You can't use "rules" for volatile; as the previous poster mentioned, you have to understand what volatile means in order to use it correctly.  This means you need to understand the "as-if" rule in C:

    In the abstract machine, all expressions are evaluated as specified
    by the semantics. An actual implementation need not evaluate part of
    an expression if it can deduce that its value is not used and that no
    needed side effects are produced (including any caused by calling a
    function or accessing a volatile object).

    The critical part here is, "An actual implementation need not evaluate part of an expression if it can deduce that its value is not used".  For example,
    int i, x;

    x = 1;
    for (i = 0; i < 10; i++)
        ;
    x = 2;
    A smart compiler can look at this code fragment, and replace it with
    int x;

    x = 2;
    because the first assignment and the loop don't have any effect on the end result of assigning 2 to x.  If you replaced x with LATA:
    int i;

    LATA = 1;
    for (i = 0; i < 10; i++)
        ;
    LATA = 2;
    Your expectation would be that 1 would be written to LATA, then a delay, then 2 would be written to LATA.  But the compiler is free to just do "LATA = 2".

    This is why LATA is volatile in the compiler's header files; every operation on LATA must be carried out exactly as stated by the programmer.

    An object that has volatile-qualified type may be modified in ways
    unknown to the implementation or have other unknown side effects.
    Therefore any expression referring to such an object shall be
    evaluated strictly according to the rules of the abstract machine

    "volatile" tells the compiler to do exactly what the programmer said to do.

    To correct the code fragment above, LATA must be volatile, and "i" must be volatile to ensure the delay loop is executed exactly as stated.

    volatile is relevant in interrupt handlers in cases like this:

    int interrupt_flag;

    int main(void) {
        interrupt_flag = 0;

        while (interrupt_flag == 0)    /* wait for interrupt */
            ;

        /* do stuff */
    }
    The compiler can look at that code and realize that interrupt_flag is 0, and will always remain 0, so there is no need for it to generate any code at all for main(), even though you might have an interrupt handler somewhere that sets interrupt_flag to 1.  The solution is to make interrupt_flag volatile, so that the compiler understands that it "may be modified in ways unknown to the implementation."
    #5
    QKernel
    Super Member
    • Total Posts : 220
    • Reward points : 0
    • Joined: 2008/09/23 17:09:44
    • Location: Alberta Canada
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 13:11:58 (permalink)
    0
    I think that most of facts and arguments are mentioned in the thread. So the answer is yes we need volatile on global variables when multiple sources like hardware and IRQ. If an RTOS is used you also have to protect global variables from multiple threads but that is simpe because a mutex can be used to save guard global variables. 

    By the way in a lot of cases global variables are used, just because you can, while automatic variables (local in the function) would be better. Automatic variables are in some cases a bit slower but they prevent a lot of bugs.

    my 2 cts

    Q▪Kernel The new generation RTOS
    ▪ Dual mode RTOS (PIC24, dsPIC and PIC32)
    ▪ Never disables interrupts
    ▪ Fibers, threads and lightweight threads
    Free download at www.quasarsoft.com
    #6
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/03 15:34:30 (permalink)
    0
    perfect John Smile
    thanks

    GENOVA :D :D ! GODO
    #7
    DavidePizzolato
    Junior Member
    • Total Posts : 95
    • Reward points : 0
    • Joined: 2010/11/25 11:55:54
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 02:31:04 (permalink)
    0
    Thank you very much for the qualified answers. Finally, a thread for the sake of discussion.
    "An actual implementation need not evaluate part of an expression if it can deduce that its value is not used"
    So we are hostages of the compiler optimization rules. I testes a small piece of code, using different variables declarations, and the C30 gives some interesting result:
    x = 1; 
    y = function1(x);
    z = function2(y);
    while (z) y++;
    if x,y,z are local short variabiles, the result is:
    mov.w #0x1,w0  
    rcall function1
    rcall function2
    cp0.w w0
    bra nz, …
    Perfect: all the variables are ignored.
     
    if x,y,z are global short variabiles, the result is:
    mov.w #0x1,w0  
    mov.w w0,x    
    rcall function1
    mov.w w0,y    
    rcall function2
    mov.w w0,z    
    cp0.w w0      
    bra z, …
    Problems here, the assignments are compiled but the loop still uses the register
     
    if x,y are global short variabiles and z is a volatile short, the result is:
    mov.w #0x1,w0   
    mov.w w0,x     
    rcall function1
    mov.w w0,y     
    rcall function2
    mov.w w0,z     

    cp0.w z        
    bra nz, …
    Much better: all the variables are used in the correct way
     
    if x,y,z are volatile short variabiles, the result is:
    mov.w #0x1,w0   
    mov.w w0,x     
    mov.w x,w0     
    rcall function1
    mov.w w0,y     
    mov.w y,w0     
    rcall function2
    mov.w w0,z     

    cp0.w z        
    bra nz, …
    Unnecessary code is added to satisfy the volatile qualifier.
     
    Back to the original question, the volatile qualifier is necessary only if we write the code using potentially bad program flows (in the example, the while loops)?
    #8
    getout
    Starting Member
    • Total Posts : 88
    • Reward points : 0
    • Joined: 2008/10/31 11:08:48
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 04:21:22 (permalink)
    +1 (1)
    Jtemples gave a detailed explanation and still you insist that in some way volatile is unnecessary.
     
    Did you read his answer?
     
    volatile is a very important attribute required when an application is confronted with concurrency.
     
    With concurrency I do not necessarily mean an RTOS. Many forms of concurrency exist. It can be an an RTOS, Interrupt Service Routines but, very important, also the hardware itself when the variables are just placeholders for hardware registers. 
     
    Would C not offer the volatile keyword, it would be impossible to write write working code using an opimizing compiler.
     
    All we could do without volatile is write assembly or use a non-optimizing compiler. Both would have benefits. Using assembly more programmers could find a job and using only non-optimizing compilers, the hardware vendors would be glad since every system would require better performing hardware.
     
    My suggestion is the following: Read the answer given by jtemples. Search this forum since many very experienced persons have written very good things about volatile in the past and finally, use Google and study C standards and so on.
     
    Then when you understand what it means to develop embedded software come back to share and learn.
    #9
    aschen0866
    Super Member
    • Total Posts : 4481
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 08:25:55 (permalink)
    +2 (2)
    I said this a while back and I'll say it again - For anyone who comes to a job interview as a C programmer, you have to test his understandings on these three basic C keywords: volatile, const and staticgrin
    #10
    Kruse
    Super Member
    • Total Posts : 1224
    • Reward points : 0
    • Joined: 2005/04/15 09:04:09
    • Location: Denmark
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 11:22:44 (permalink)
    0
    LoL huuh I thought I understood the concept of keyword volatile.
    Thank you jtemples.

    A PIC listens to your commands -not your intentions.
    #11
    threedog
    Super Member
    • Total Posts : 998
    • Reward points : 0
    • Joined: 2009/12/04 12:28:11
    • Location: Boise
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 11:51:18 (permalink)
    0
    Maybe you are using the lite version of the compiler and all optimization has been turned off.
    If you want to ignore "volatile" then use
     
    -O0
    [size=1 font="courier new"][size=1 font="courier new"] -fvolatile
    [size=1 font="courier new"][size=1 font="courier new"] -fvolatile-global
    [size=2 font="courier new"] -fvolatile-static
     
    I assume the code bloat will acceptable.
     
     
    #12
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 12:02:34 (permalink)
    0
    Smile

    GENOVA :D :D ! GODO
    #13
    sborden
    Super Member
    • Total Posts : 1932
    • Reward points : 0
    • Joined: 2010/08/05 02:12:53
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 13:26:38 (permalink)
    0
    Understanding C's purpose in life will help you understand why there is a "volatile" qualifier.

    C is a rope meant to build bridges, ladders, harnesses, etc.  Very useful, very multi-purpose.

    But it can also hang you.

    This is by design.  It is up to you how to use the rope.

    C will build a bridge across the bay rather than making you have to drive all the way around it.  "volatile" just tells the compiler that a particular variable wants to take the scenic route around the bay.
    #14
    OccamMD
    Super Member
    • Total Posts : 1692
    • Reward points : 0
    • Joined: 2005/06/17 08:41:06
    • Location: Tampa, FL
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 14:05:04 (permalink)
    0
    Remember too, though, that volatile does nothing to enforce atomic access to variables.  If you have globals that are shared between interrupts or foreground/background tasks, then you need to protect them during access via the lower priority code

    Also, volatile is not just about caching, it is also about order of execution and hoisting.

    Volatile is mis-handled by many compilers, so you should actually try to eliminate it's need via accessor functions.  (In my opinion).

    http://www.cs.utah.edu/~r.../emsoft08-preprint.pdf
    #15
    sborden
    Super Member
    • Total Posts : 1932
    • Reward points : 0
    • Joined: 2010/08/05 02:12:53
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/04 14:41:40 (permalink)
    0
    *ouch*
    #16
    DavidePizzolato
    Junior Member
    • Total Posts : 95
    • Reward points : 0
    • Joined: 2010/11/25 11:55:54
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2011/02/07 01:36:39 (permalink)
    0
    10 years of C/C++ programming and still feel like a newbie. So I keep avoiding volatiles, just for a matter of style.
    There are situations where volatiles are really necessary (device peripherals) but not in user code, using proper habits.
    post edited by DavidePizzolato - 2011/02/07 01:38:27
    #17
    pic_guy
    Starting Member
    • Total Posts : 39
    • Reward points : 0
    • Joined: 2007/01/25 13:15:09
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2019/05/21 11:37:41 (permalink)
    0
    I had a question about volatile and thought it'd be useful to expand on this thread then start a new one.  I'm using a PIC32MZ series chip and am not using optimization.
    1. Perhaps as a matter of best practice it would be good to use volatile, but do you need it to write safe working code if you never plan to use optimization?
    2. Are there other needed/useful effects of using volatile if the optimizer is turned off?
    #18
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11248
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re:Do we really need the volatile qualifier? 2019/05/21 12:10:04 (permalink)
    +1 (1)
    am not using optimization

     
    I would never assume that turning off a compiler's optimization would give me a 100% guarantee that not one single instruction was optimized away.
    #19
    LdB_ECM
    Senior Member
    • Total Posts : 125
    • Reward points : 0
    • Joined: 2019/04/16 22:01:25
    • Location: 0
    • Status: offline
    Re:Do we really need the volatile qualifier? 2019/05/21 12:18:11 (permalink)
    0
    The volatile is only partly related to optimization ... it basically says anytime you want to access this thing you have to re-read the value you can't carry it in a register ... so it stops the optimizer register carrying the value. So you use the value in two lines of code one after another it will go fetch the value from the memory address twice.
     
    That is it, the total relationship to the optimizer.
     
    You still aren't safe so now you need to understand the problem, you have two things that are not synchronized accessing the same location of memory. Now if volatile will save you depends on the opcode sequence so lets make a simple count integer
     
    One process increments the count, one process decrements the count and they both go for the integer randomly.
     
    So long as the integer loads and saves as a single opcode instruction volatile will save you because the volatile statement means the code can't carry the value in a register therefore the value at the integer is always correct regardless of even two processes going for it one after another.
     
    When it won't save you is if the load and save of the integer takes two opcode like a load high byte load low byte because one process can for example have written only the high byte and at that exact instant the other process reads and it now gets the low of the value being written and the high of the old value.
     
    So you can only use volatile to aide with synchronization on single opcode things, if it is multi opcode access you are dead in the water. This is the bit that gets lost with newbies because they don't get the whole thing that sometimes C code sprays to multiple opcodes.
     
    The moment you get multiple opcode sections that need to be synchronized you have to write them in a special way called lockless programming or you need to put a lock primitive on it. Something like a binary semaphore is usually trivial on most systems 
    #20
    Jump to:
    © 2019 APG vNext Commercial Version 4.5