What are atomic operations and why do they matter?
An atomic operation is an operation that completes in its entirety without being interrupted — it is indivisible. From the perspective of any other task or ISR, an atomic operation either has not started or has fully completed; there is no visible intermediate state.
On a 32-bit ARM Cortex-M processor, a single 32-bit load or store instruction is naturally atomic — reading or writing a uint32_t at an aligned address is one instruction. However, a 64-bit access on a 32-bit core requires two instructions and is NOT atomic. Similarly, read-modify-write operations like counter++ are NOT atomic because they compile to three instructions: load, increment, store. If an ISR fires between the load and store and modifies the same variable, the ISR's update is lost.
Solutions for making compound operations atomic include: (1) disabling interrupts around the operation (simple but increases interrupt latency); (2) using LDREX/STREX (exclusive load/store) instructions on Cortex-M, which implement lock-free atomic operations by detecting if another context modified the variable between the load and store, and retrying if so; (3) using C11 _Atomic types or compiler intrinsics like __atomic_fetch_add; (4) using an RTOS mutex for longer critical sections. The choice depends on the duration of the critical section and whether it is accessed from ISR context (where mutexes are not available).
Source: Operating Systems & RTOS Q&A
