Search topics...
Operating Systems & RTOSReentrant Functions and volatileintermediate

What does the volatile keyword do and when is it required in embedded C?

0 upvotes
Practice with AISoon
Study the fundamentals first — Operating Systems & RTOS topic page

The volatile keyword tells the compiler that a variable's value may change at any time without any action being taken by the code the compiler finds nearby. This prevents the compiler from optimizing away reads or caching the value in a register.

You must use volatile in three situations in embedded C: (1) Hardware registers — peripheral registers (e.g., a UART status register) can change at any time due to hardware events. Without volatile, the compiler might read the register once, cache it in a register, and never re-read it, causing your polling loop to spin forever. (2) Variables shared between an ISR and a task — without volatile, the compiler may assume the variable never changes within the main loop (since it cannot see the ISR modifying it) and optimize away the check. (3) Variables shared between multiple tasks in some cases, though a proper synchronization primitive (mutex, queue) usually handles the memory visibility issue.

A classic interview trap: "Does volatile make an operation atomic?" No. On a 32-bit ARM, reading a volatile uint32_t is atomic because it is a single load instruction, but incrementing it (x++) is a read-modify-write sequence that is not atomic even with volatile. For atomicity, you need either disable interrupts, use a mutex, or use hardware atomic instructions (e.g., LDREX/STREX on Cortex-M). Another trap: volatile does not guarantee memory ordering between different variables — for that, you need memory barriers.

Source: Operating Systems & RTOS Q&A