The Volatile Keyword

No matter who you ask, misuse of this keyword will go very high on the list of things that make embedded systems crash and burn.

The main reason to declare an object as volatile is to inform the compiler that the value of the object can change in ways unknown to the compiler and thus all accesses to the object must be preserved. Three typical scenarios are creating the need for volatile objects:

  • Shared access; the object is shared between several tasks in a multitasking environment or is accessed both from a single thread of execution and one or more interrupt service routines.
  • Trigger access; as for a memory-mapped hardware device where the fact that an access occurs affects the device
  • Modified access; where the contents of the object can change in ways not known to the compiler

So, what kind of guarantees do you get from the compiler if you apply the volatile keyword to an object declaration? Essentially the following: All read and write accesses are preserved. That’s it!

Depending on the target architecture you might also get all accesses complete, performed in the order given in the abstract machine and, if applicable, atomic

Is the code in the figure thread-safe and interrupt-safe, given that the volatile object can be accessed from different execution contexts? Both the load from memory and the store to memory of the value of vol are atomic since this is for a 32-bit load/store architecture. But the source statement is not atomic! We can still be hit by a context switch or interrupt somewhere in between the three instructions making up the vol++ statement.

How to cope

  • Never assume that volatile means atomic except for certain memory accesses!

  • Make sure code that does more than just an atomic read or write to a volatile object is guarded by proper serialization primitives, like a mutex, or by interrupt disabling, if the object can be accessed from different execution contexts.

  • Cover the proper usage of the volatile keyword and serialization primitives in your coding standard.

  • Consider reviewing the usage of all global objects, including file-scoped static objects in existing code.