What are memory barriers (DSB, DMB, ISB) and when do you need them?
ARM Cortex-M provides three memory barrier instructions that control the ordering of memory operations and instruction execution. They exist because modern processors — especially Cortex-M7 with its write buffers, caches, and multi-stage pipeline — can reorder operations for performance in ways that break hardware interaction and configuration sequences.
DSB (Data Synchronization Barrier): Ensures all memory accesses before the DSB complete before any memory access after the DSB begins. The most common use case is after enabling a peripheral clock: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; __DSB(); — the clock enable write must propagate through the bus to the peripheral before you write to GPIOA registers. Without the DSB, the subsequent register write may execute before the clock is active, and the write is silently lost. Also required after writing to the MPU to ensure the new memory attributes are in effect before the next memory access.
DMB (Data Memory Barrier): Ensures all memory accesses before the DMB are observed by other bus masters before any memory accesses after the DMB. This is critical for DMA buffer handoff: when the CPU fills a TX buffer and then sets a DMA enable bit, the DMB guarantees that all buffer writes are visible in SRAM before the DMA starts reading. Without it, the DMA might see partially-updated buffer contents on systems with write buffers or out-of-order memory.
ISB (Instruction Synchronization Barrier): Flushes the pipeline so that all subsequent instructions are re-fetched. Required after changes that affect instruction execution: updating the VTOR (Vector Table Offset Register) — without ISB, an interrupt arriving immediately after might use the old vector table still in the pipeline's fetch stage; modifying MPU regions — the pipeline may have already fetched instructions under the old memory attributes; or changing the CONTROL register (switching between MSP/PSP or privilege levels). In practice, the most common pattern is __DSB(); __ISB(); after MPU or VTOR configuration, ensuring both data writes and instruction fetches observe the new settings.
Source: CPU Fundamentals Q&A
